分布式爬虫架构
今天面试, 说到了分布式爬虫, 其实每个框架已经实现了高并发的性能, 通过异步等等方式, 把性能发挥到了极致. 但在做高铁的时候无聊, 便设计了一个非常有意思的架构.
这个架构, 是一个思维比较开放形式.主要的思想就是把所有的主要构件拆成单独的worker类型, 然后通过一个总的引擎来控制不同的worker与task, 所有的worker进程为单位, worker内是否需要多线程或异步就看大家自己的需要了, 对于多cpu的服务器可以非常迅速的挖掘潜力,发挥极致的爬取性能.当然我还不知道目前有没有这类架构形式的框架.
如果觉得有问题或需要改进, 欢迎大家发邮件yanwei.li.24#at#gmail.com
以下是随手画的草图.
详细描述
- Engine 层的主要作用:
- 按需求与比例增加或停止每台机器的worker数量以及worker 比例, 包括 Downloader worker, Parser worker, Pipeline Worker.
- 对池子里的任务进行控制, 分发任务到各worker.
- Downloader Worker:
Downloader可以自由定制, 你可以用nodejs做异步高并发的下载, 也可以用c写出个高效率的Downloader
- Parser Worker
可以毫无疑问的选用脚本, javascript或者python都可以, 重要的是可以针对不同的parser快速编写, 快速修改.
- Pipeline
由于可能是远程存储, 也有可能有延迟, 也有可能会断线, 还有可能会分到不同的块区等等, 这些逻辑都在这里写就可以了, 这个有时候你会觉得更像个Uploader.
Pools:
- 每个worker完成一个小任务单元都需要把结果存储到下一个pool里, 所有的worker等待Engine分发task.
- 如果有pool产生堵塞, 减少上层worker的数量, 增加下层worker数量.
- 如果pool内的task消耗很快, 甚至总是让池子空了, 增加上层worker数量, 减少下层worker数量.
- Engine发放task要以组发放, 一组task=1 batch, 这样发放任务会减少分发运算与上下文数量.
该架构的优点
- 天然的分布式, 线性增加机器即可.所有任务共享, 共同消化, 宕机机器后任务仍然精准完成.
- 天然多进程, 程序调度与性能发挥不需要额外处理, 完全依靠系统足够.
- worker独立, 可以自由定制, 针对不同的worker类型进行优化.
- worker分离, 通过引擎的控制可以让不同类型的Worker工作协调, 资源分配均匀, 无浪费.
- 轻量与定制方便, 队友合作可以不关心谁用什么语言, 抓取用c, 解析用javascript, 上传再来一个pythoner做, 只要pool格式做好, 其他都ok.
架构很粗糙, 但我还需要给这个架构添加点血肉.
要有血有肉
Master-Engine
Local-Engine
–Downloader |
—-some-downloader1 |
—-some-downloader1_lib |
—-some-downloader2 |
–Paser |
—-some-parser1 |
—-some-parser2 |
—-some-parser2_lib |
–Pipeline |
—-some-pipeline1 |
—-some-pipeline1_lib |
—-some-pipeline2 |
我们大体约定 Request的格式, id,url,some-downloader,retry_time,status,created_time,meta_data
我们大体约定 Response的格式, id,url,some-parser,response-context,status,meta_data
我们对item的约定是 item_name,some-pipeline,value(dict)
这样整个任务流就完成了.
为了能够反反爬虫, 比如某个downloader, 如果一旦某网站被进止抓取,比如跳转到输入验证码页, 可以写不同的downloader的wrapper来引用不同的middleware.
该middleware的作用就是向engine做出反馈, 然后engine会通知所有的downloader, downloader把任务放回池子里, 如果验证码不通过, engine不会分发该网站的task.
计算机软件应该包括程序与数据, 也可以完全叫做数据的集合, 因为cpu处理的一切都是在靠一些逻辑数据处理一些人需要的数据. Lisp中有说: “代码即数据”, 就是这个意思.
对于爬虫, 最重要的不是架构, 不是效率, 而是数据的完整.
而不管是什么架构的设计, 先忘掉设计模式, 忘掉异常处理, 忘掉所有的乱起八糟, 然后回头围绕数据来做, 事情就会得到极大的简化, 也就是经典.
本文说的架构就是围绕数据而发散来的.