0

0

如何使用Golang实现一个基础的Web爬虫排队系统

P粉602998670

P粉602998670

发布时间:2026-02-13 01:21:26

|

282人浏览过

|

来源于php中文网

原创

直接用 time.sleep 控制爬取间隔是错的,因其无法支持并发调度、失败重试、域名隔离限流,且会阻塞 goroutine、浪费资源;正确做法是为每个标准化域名分配独立 rate.limiter 实例,并透传带超时的 context。

如何使用golang实现一个基础的web爬虫排队系统

为什么直接用 time.Sleep 控制爬取间隔是错的

它无法应对并发任务调度、失败重试、优先级调整,还会让整个 goroutine 阻塞,浪费资源。真实场景里,你不是“等几秒再发一个请求”,而是“确保每秒最多发 N 个请求,且不同域名要独立限流”。

  • time.Sleep 会导致所有任务共享同一延迟逻辑,一旦某个 URL 报错重试,就拖慢后续全部任务
  • 不同目标站点对 QPS 敏感度不同,硬编码 sleep 时间等于把 example.comapi.github.com 当成同一个限流桶
  • goroutine 不会因为 sleep 就自动释放,大量 pending 的 sleep 状态会堆积内存和调度开销

正确做法是用带权重与域名隔离的令牌桶,配合 channel 控制消费节奏。比如用 golang.org/x/time/rateLimiter,每个域名配一个独立 *rate.Limiter 实例。

如何为不同域名分配独立限流器并复用

核心在于把域名作为 key 构建 map,避免每次请求都新建或查找失败。别用全局单例 limiter,也别在 handler 里临时 new —— 这两种都会导致限流失效或内存泄漏。

  • 初始化时用 sync.Map 或带读写锁的普通 map 存储 map[string]*rate.Limiter
  • 获取 limiter 时先 Load,不存在再 Store 新建,参数如 rate.Every(1 * time.Second)burst=5 要按域名策略配置
  • 注意:不要把 http.Request.Host 直接当 key,得先做标准化(去掉 port、转小写),否则 api.example.com:443API.EXAMPLE.COM 会被当成两个域名

示例片段:

limiter, _ := limiters.LoadOrStore(domain, rate.NewLimiter(rate.Every(2*time.Second), 1))
后续调用 limiter.Wait(ctx) 即可阻塞等待令牌。

立即学习go语言免费学习笔记(深入)”;

花生AI
花生AI

B站推出的AI视频创作工具

下载

context.Context 在排队环节必须传透的原因

爬虫排队不是纯内存操作,它常嵌套在 HTTP handler、定时任务或消息消费中,任何一环超时或取消,排队中的请求都该立刻退出,否则 goroutine 泄漏、连接堆积、重试风暴全来了。

  • 所有 Limiter.Wait 必须传入带 timeout 的 ctx,比如 ctx, cancel := context.WithTimeout(parentCtx, 30*time.Second)
  • 如果上游已 cancel(如用户关闭页面、K8s 发送 SIGTERM),Wait 会立即返回 context.Canceled 错误,你不检查就继续发请求,等于忽略信号
  • 别在排队前就 http.NewRequestWithContext,而要在真正准备发起 HTTP 请求那一刻才绑定 context —— 排队阶段的 context 只管“能不能取令牌”,不关 HTTP 什么事

常见错误日志:context deadline exceeded 出现在 Limiter.Wait 而非 http.Do,说明排队卡住了,得查 limiter burst 是否设太小,或上游 ctx timeout 是否过短。

为什么不用 channel 做任务队列而选 sync.Pool + 有限长 slice

初学者容易想当然用 chan *Task 做缓冲队列,但实际压测会发现:channel 阻塞写入导致生产者卡死、GC 压力大、无法按优先级插队、扩容缩容困难。

  • 高吞吐下,chan 的锁竞争比 slice+mutex 更重;尤其当消费者偶尔延迟,channel 缓冲区满后所有生产者全停摆
  • sync.Pool 复用 []*Task 切片,配合 atomic.Int64 计数器控制总长度(如最多存 10000 个待爬 URL),内存更可控
  • 需要优先级时,slice 可以快速排序或分 bucket(如 status=200 的放 front,404 放 back),channel 无法做到

关键点:不是“有没有队列”,而是“谁控制入队节奏”。真正的排队逻辑在 limiter.Wait,而不是 channel 的容量。队列只是暂存,不是调度器。

事情说清了就结束。真正难的是域名识别的健壮性、限流参数的动态加载、以及 context 取消后残留 goroutine 的清理——这些不会报错,但会让系统在流量高峰时悄悄失联。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
golang如何定义变量
golang如何定义变量

golang定义变量的方法:1、声明变量并赋予初始值“var age int =值”;2、声明变量但不赋初始值“var age int”;3、使用短变量声明“age :=值”等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

206

2024.02.23

golang有哪些数据转换方法
golang有哪些数据转换方法

golang数据转换方法:1、类型转换操作符;2、类型断言;3、字符串和数字之间的转换;4、JSON序列化和反序列化;5、使用标准库进行数据转换;6、使用第三方库进行数据转换;7、自定义数据转换函数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

235

2024.02.23

golang常用库有哪些
golang常用库有哪些

golang常用库有:1、标准库;2、字符串处理库;3、网络库;4、加密库;5、压缩库;6、xml和json解析库;7、日期和时间库;8、数据库操作库;9、文件操作库;10、图像处理库。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

346

2024.02.23

golang和python的区别是什么
golang和python的区别是什么

golang和python的区别是:1、golang是一种编译型语言,而python是一种解释型语言;2、golang天生支持并发编程,而python对并发与并行的支持相对较弱等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

212

2024.03.05

golang是免费的吗
golang是免费的吗

golang是免费的。golang是google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的开源编程语言,采用bsd开源协议。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

402

2024.05.21

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

322

2025.06.09

golang相关判断方法
golang相关判断方法

本专题整合了golang相关判断方法,想了解更详细的相关内容,请阅读下面的文章。

197

2025.06.10

golang数组使用方法
golang数组使用方法

本专题整合了golang数组用法,想了解更多的相关内容,请阅读专题下面的文章。

804

2025.06.17

c语言 数据类型
c语言 数据类型

本专题整合了c语言数据类型相关内容,阅读专题下面的文章了解更多详细内容。

4

2026.02.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Go 教程
Go 教程

共32课时 | 5万人学习

Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号