crawler源码分析
进入主函数
初始化配置
如果是master,初始化节点ip列表
a. redis操作
设置 crawl:master:state = starting
删除 up
删除 node:*,
删除 crawl:cidr:*
删除 pending
b.获取节点ip列表
从 seeders 获得列表,会过滤掉 exclude ip list 里的地址
[(2, 0, 0, '', ('82.221.111.136', 0))]
redis设值
pending = (address, CONF['port'], TO_SERVICES)
= ('82.221.111.136', 8333, 1)
从 bogons 地址查bogon ip,加入exclude ip list
crawl:master:state = running
- 启动task(消费者,默认 700-1 个)
在true循环里
如果 crawl:master:state != running,睡眠
从 pending 列表里随便取一个节点出来(取不到会sleep)
key = node:{}-{}-****{} (ADDRESS-PORT-SERVICES)
判断redis有没有 key
如果有,coninue
如果没有
如果地址是 ipv6,格式化成 CIDR 的表示形式,redis中 crawl:cidr:****{} 的值加 1
connect ( key )
connect方法
设值 node:{}-{}-****{} = ''
取值 height ,如果有的话
实例化一个连接对象 conn,调用 protocol类的 Connect( address, etc. ) 方法
conn.open(),建立socket连接
conn.handshake() (= handshake_msgs)
把 命令发送的节点
接收数据,并发送 命令回节点
接收数据,收到了一些版本信息,包括 块高度
conn.getaddr()
发送 命令,不自动接收数据
手动接收数据
resids设值并设置过期时间8小时 height:{}-{}-****{} (address, port, from_services)
把 getaddr 获取到的节点列表累加到 pending 中
如果 handshake_msgs 中的 services 和 发出去的 不一样
key = "node:{}-{}-{}"
设值 key = ''
把 key 累加到 up 列表
- 启动一个corn线程 (生产者)
startTime init
在 true 循环里面
获取 pending 的总数
如果 pending != 0 睡眠几秒
如果 pending == 0
redis设值 crawl:master:state = starting
redis设值 elapsed = 当前时间 - 进入cron线程的时间
restart()
redis操作
查询 up (=nodes)
把 nodes 里的 address 累加到 pending 里
删除 up
删除 node:*
删除 crawl:cidr:*
把 bitnodes 官方已知的节点累加到 pending 里(默认关闭)
redis设值 nodes lpush (timestamp, reachable_nodes)
dump(nodes) (=h)
redis 根据 height:{}-{}-****{} 查询每一个 node 的 height
输出 [address, port, services, height] 到 json文件
return 出现次数最多的块高度
redis设值 height = h
战略性睡眠
startTime inti
redis设值 crawl:master:state = running
最后输出的文件
问题:
为什么默认worker数量是700 ?
一个crawler 700个worker,三个crawler一共2000个task同时消费 pending,实际过程中penging列表里大概 25000 左右个待处理节点。
这个crawler脚本获取到的关键信息主要是块高度,要保证在出一个块的时间内处理完pending。假设一个task请求一个节点(发请求、接收数据、数据处理)共耗时 20s,2000个task处理完 25000 个节点共耗时 250s 大概 4 到 5 分钟。
这个文件里设置了 elapsed 的值但是没有用过
在ping那个脚本里用了。
为什么设置了 crawl:cidr:* 的值,但没有用过
up 和 pending 是什么关系,为什么第一次要把不是1的节点放到 up 里;后续的 up 里会充斥各种services的节点