技术实现:通过Redis**队列的形式,对知乎的标签页进行广度优先遍历,通过FIFO,实现分布式爬虫,并协同抓取全知乎的标签及子标签的树状结构,将此全量树状结构存储入MySQL数据库。此机制保证任何一个爬虫技能单独而协同。
获取连接耗时26秒.
响应数据入库19秒
HTTP请求:通信链路如下图所示,经历12次网络IO。
上述12个步骤都是串行关系,粗略计算,基本IO损耗 : >3倍
损耗成本:百毫秒-秒级(主要)
发生阶段:4,10
NDS网关是最大不可控因素, 问题如下:
-
高并发情况下,连接数耗尽,导致大量请求超时, 超时时间可调.
在测试环境,多网关实例效果更优,如:2实例 250连接数 > 1实例 500连接数**
-
决定连接数因素有二:NDS实例连接数 ,NDS全局总连接数.
在测试环境,网关实例存在总连接数限制,如:开通2个实例,1000连接数, 实际Mysql检测到的连接数不足。
- 驱动包偶发空指针异常;NetPackage对象占用内存,致使OOM异常风险.
发生阶段:3,5,8,10
措施:
- 平台标准JSON序列化工具
- 并行执行
发生阶段:5,10
措施:
-
外网轮询间隔, 等待响应
- 有请求时,不间断循环
- 无请求时,休眠,等待唤醒
-
内网轮询, 等待请求
-
无请求时休眠5ms(参数配置)
-
批量获得http请求,线程池并行处理(参数配置),获取响应即时入库
-
发生阶段:3,4,9,10
主要瓶颈:
- 数据库连接获取,连接数耗尽
- 大请求,大响应写入数据库
措施:
- 仅基于一张表,无任何关联查询
- 请求处理完成后,记录实时清除,数据库表始终维持在 0 ~ 并发数之间
- 所有语句均基于索引
- 使用连接池
数据大小 | 并发数 | 平均响应时间 | 错误率 |
---|---|---|---|
1k | 10 | 0.36 | 0% |
1k | 50 | 0.67 | 0% |
1k | 100 | 1.22 | 0% |
1k | 200 | 3.39 | 0% |
5k | 10 | 0.59 | 0% |
5k | 50 | 0.82 | 0% |
5k | 100 | 1.56 | 0% |
5k | 200 | 4.18 | 0% |
10K | 10 | 0.66 | 0% |
10k | 50 | 0.87 | 0% |
10K | 100 | 1.86 | 0% |
10K | 200 | 4.91 | 0% |
200K | 10 | 0.93 | 0% |
200K | 50 | 1.15 | 0% |
200K | 100 | 2.11 | 0% |
200K | 200 | 5.14 | 0% |
1024k | 10 | 1.69 | 0% |
1024k | 50 | 5.93 | 0% |
1024k | 100 | 14.02 | 0% |
1024k | 200 | 21.98 | 0% |
1024k | 250 | 8.847 | 11% |
随着总传输数据上升突破某节点,错误率突然显现
单实例
数据大小 | 并发数 | 平均响应时间 | 错误率 |
---|---|---|---|
10K | 300 | 4.847 | 11% |
10K | 400 | 8.496 | 16% |
10K | 500 | 10.55 | 52.50% |
双实例
数据大小 | 并发数 | 平均响应时间 | 错误率 |
---|---|---|---|
10K | 300 | 3.214 | 0% |
10K | 400 | 3.784 | 0% |
10K | 500 | 2.694 | 5.13% |
总数据库连接数相同的情况下,双实例的错误率区别明显
网闸
数据大小 | 并发数 | 平均响应时间 | 错误率 |
---|---|---|---|
10K | 500 | 4.847 | 11% |
直连Mysql
数据大小 | 并发数 | 平均响应时间 | 错误率 |
---|---|---|---|
10K | 500 | 3.388 | 0% |
通过网闸与否,在性能上存在波动,数据不明显,但错误率区别明显
- 不恰当的建立连接,导致连接数耗尽
- 生产者空转,在没有请求的情况下去获取响应
- 不恰当清除,consumer启动时清空数据库
- 增加心跳,防止网闸启动休眠断线机制,长时间没流量半关闭socket,
- 一个网闸通道可以支持200并发1M的请求数,无法通过配置网闸参数再提高
- 多通道,多实例部署:测试机器,最多可以支持2网闸通道400并发1M的请求数,再提高会出现OOM,或者超长的延迟
内容 | 损耗 | 措施&备注 | 实现情况 | 效果 |
---|---|---|---|---|
请求,响应序列化,反序列化 | 并行处理 | 已实现 | * | |
NDS网关基本损耗 | 主要,秒级 | 添加连接数,添加实例 | 现场实施 | ***** |
轮询间隔 | 轮询间隔参数化 | 已实现 | * | |
各阶段IO | 主要,秒级 | HTTP协议用GZIP传输 | 现场实施 | ** |
数据库交互 | 索引,单表,记录数少,连接池 | 已实现 | ** |
日志关键节点
0 [P] 到达 | |
1 [P] 准备连接 | |
2 [P] 连接获取 | |
3 [P] 完成入库 | |
4 [C] 准备连接 (批处理) | |
5 [C] 连接完成 (批处理) | |
6 [C] 请求序列化 (批处理) | |
7 [C] 请求状态更新 (批处理) | |
8 [C] HTTP准备发送 | |
9 [C] HTTP响应获取 | |
10 [C] HTTP响应入库 | |
11 [P] 准备连接【批】 | |
12 [P] 连接完成【批】 | |
13 [P] 响应读取【批】 | |
14 [P] 响应序列化 | |
15 [P] 返回前端并完成 | |