demo.pyspider.org 部署经验

经常有人会问 pyspider 怎么进行分布式部署,这里以 demo.pyspider.org 的实际部署经验做一个例子。

因为 pyspider 支持分布式部署,为了验证也好,为了省钱多蹭 CPU 也好, demo.pyspider.org 通过 docker 部署在同一机房的 3 台 VPS 上,VPS 间有内网传输(实际通过 tinc)。

使用 docker 的原因是实际上 pyspider 能够运行任何 python 脚本,至少需要 docker 环境逃逸。

demo.pyspider.org 的数据库为 PostgreSQL,理由是测试目的,磁盘占用和性能的折中。消息队列为 Redis,因为部署简单。

它们也是跑在 docker 中的:

1

2

docker run --name postgres -v /data/postgres/:/var/lib/postgresql/data -d -p $LOCAL_IP:5432:5432 -e POSTGRES_PASSWORD="" postgres

docker run --name redis -d -p $LOCAL_IP:6379:6379 redis

由于前面说过,机器间有内网,通过绑定内网 IP,没有做鉴权(反正 demo 会泄露)。

由于 scheduler 只能运行一个,并且需要进行大量的数据库操作,它与上面的数据库和消息队列部署在一台单独的机器上。

1

2

3

4

5

6

docker run --name scheduler -d -p $LOCAL_IP:23333:23333 --restart=always binux/pyspider \

--taskdb "sqlalchemy+postgresql+taskdb://[email protected]/taskdb" \

--resultdb "sqlalchemy+postgresql+resultdb://[email protected]/resultdb" \

--projectdb "sqlalchemy+postgresql+projectdb://[email protected]/projectdb" \

--message-queue "redis://10.21.0.7:6379/1" \

scheduler --inqueue-limit 5000 --delete-time 43200

所有其他的组件(fetcher, processor, result_worker)在剩余的两台 VPS 上以相同的配置启动。他们都是通过 docker-compose 管理的

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

phantomjs:

image: 'binux/pyspider:latest'

command: phantomjs

cpu_shares: 512

environment:

- 'EXCLUDE_PORTS=5000,23333,24444'

expose:

- '25555'

mem_limit: 512m

restart: always

phantomjs-lb:

image: 'dockercloud/haproxy:latest'

links:

- phantomjs

restart: always

fetcher:

image: 'binux/pyspider:latest'

command: '--message-queue "redis://10.21.0.7:6379/1" --phantomjs-proxy "phantomjs:80" fetcher --xmlrpc'

cpu_shares: 512

environment:

- 'EXCLUDE_PORTS=5000,25555,23333'

links:

- 'phantomjs-lb:phantomjs'

mem_limit: 128m

restart: always

fetcher-lb:

image: 'dockercloud/haproxy:latest'

links:

- fetcher

restart: always

processor:

image: 'binux/pyspider:latest'

command: '--projectdb "sqlalchemy+postgresql+projectdb://[email protected]/projectdb" --message-queue "redis://10.21.0.7:6379/1" processor'

cpu_shares: 512

mem_limit: 256m

restart: always

result-worker:

image: 'binux/pyspider:latest'

command: '--taskdb "sqlalchemy+postgresql+taskdb://[email protected]/taskdb" --projectdb "sqlalchemy+postgresql+projectdb://[email protected]/projectdb" --resultdb "sqlalchemy+postgresql+resultdb://[email protected]/resultdb" --message-queue "redis://10.21.0.7:6379/1" result_worker'

cpu_shares: 512

mem_limit: 256m

restart: always

webui:

image: 'binux/pyspider:latest'

command: '--taskdb "sqlalchemy+postgresql+taskdb://[email protected]/taskdb" --projectdb "sqlalchemy+postgresql+projectdb://[email protected]/projectdb" --resultdb "sqlalchemy+postgresql+resultdb://[email protected]/resultdb" --message-queue "redis://10.21.0.7:6379/1" webui --max-rate 0.2 --max-burst 3 --scheduler-rpc "http://o4.i.binux.me:23333/" --fetcher-rpc "http://fetcher/"'

cpu_shares: 512

environment:

- 'EXCLUDE_PORTS=24444,25555,23333'

links:

- 'fetcher-lb:fetcher'

mem_limit: 256m

restart: always

webui-lb:

image: 'dockercloud/haproxy:latest'

links:

- webui

restart: always

nginx:

image: 'nginx'

links:

- 'webui-lb:HAPROXY'

ports:

- '0.0.0.0:80:80'

volumes:

- /home/binux/nfs/profile/nginx/nginx.conf:/etc/nginx/nginx.conf

- /home/binux/nfs/profile/nginx/conf.d/:/etc/nginx/conf.d/

restart: always

然后通过 docker-compose scale phantomjs=2 processor=2 webui=4 指定启动两个 phantomjs 进程,两个 processor 进程,4个 webui 进程。

phantomjs

由于 phantomjs 有内存泄露问题,限制下内存就好了。EXCLUDE_PORTS 是为了下面的 haproxy 能够正确的均衡负载正确端口。

phantomjs-lb

通过 haproxy 自动负载均衡,只要将服务链接上去,就会将请求分发到不定多个 phantomjs 实例上,同时只暴露一个对外服务端口。

fetcher

链接 phantomjs-lb:phantomjs,注意这里的 --phantomjs-proxy "phantomjs:80"

由于 fetcher 是异步 http 请求,如果没有发生堵塞,单个 fetcher 一般就足够了。

fetcher-lb

同 phantomjs-lb

processor

processor 为最消耗 CPU 的组件,建议根据 CPU 的数量部署 +1/2 个。

result-worker

默认的 result-worker 只是在写数据库,除非发生堵塞,或者你重载了 result_worker,一个就够。

webui

首先,webui 为了安全性,限制了最大抓取速率 --max-rate 0.2 --max-burst 3

然后通过实际的 fetcher 进行抓取 --fetcher-rpc "http://fetcher/" 而不是 webui 自己发起请求,最大程度模拟环境(IP,库版本),因为以前遇到过调试的时候没问题,跑起来失败,然后在调试器复现又没法复现的问题。fetcher-rpc 可以不用,这样的会 webui 会自己直接发起请求。

因为 demo.pyspider.org 主要就是提供通过页面来尝试 pyspider, 这里的负载较大,而且实现上是同步的,任何脚本执行,抓取都是堵塞了,多一些 webui 会比较好。

webui-lb

同 phantpmjs-lb

nginx

这里做了一些前端缓存

其他

因为懒得管,每小时我会重启除了 scheduler 以外的其他组件(反正会重试)。


为您推荐了相关的技术文章:

  1. rfyiamcool/toproxy: 😈 high performance simple tornado http proxy.
  2. Pwn2Own2017专题:VMWARE UAF漏洞分析
  3. 胖哈勃杯第十三届CUIT校赛官方Writeup
  4. 透过F5获取服务器真实内网IP - 勾陈安全实验室
  5. 【经典好文】- 攻击JavaWeb应用 [1] - ThreatHunter

原文链接: binux.blog