运维学python之爬虫中级篇(三)分布式进程

相对线程来讲,进程更稳定一些,线程只是在同一台机器上利用多CPU,没法实现不一样机器的共享,而多进程则能够实现分布到不一样机器去运行,应用到爬虫上,就例如:咱们要爬取网站图片,若是使用多进程的话,则一个进程负责获取图片url,将url放入队列中,另外的进程负责读取和下载,如今把这个进程作成分布式,一台机器负责抓取,另外一台负责下载。windows

1 介绍

Python的multiprocessing模块不但支持多进程,其中managers子模块还支持把多进程分布到多台机器上。managers提供了一种建立数据的方法,能够在不一样的进程之间共享数据,包括在不一样机器上运行的进程之间经过网络共享。manage对象控制管理共享对象的服务器进程。其余进程能够经过使用代理访问共享对象。服务器

2 服务进程

咱们先来看服务进程,服务进程主要工做:网络

  • 服务进程负责启动Queue
  • 把Queue注册到网络上
  • 往Queue里面写入任务
    咱们用代码来看实际效果:
# -*- coding: utf-8 -*-

import queue
from multiprocessing.managers import BaseManager

# 建立task_queue和result_queue对了用来存听任务和结果
task_queue = queue.Queue()
result_queue = queue.Queue()

class QueueManager(BaseManager):
    """
    继承BaseManager
    """
    pass

# 把建立的两个队列注册到网络上,利用register方法,callable参数关联对象
# 注意windows下绑定调用接口不能使用lambda
QueueManager.register('get_task_queue', callable=lambda: task_queue)
QueueManager.register('get_result_queue', callable=lambda: result_queue)
# 绑定5000端口, 设置密钥
manager = QueueManager(address=('', 5000), authkey=b'abc')
# 启动queue,监听通道
manager.start()
# 得到经过网络访问的对象,注意分布式进程必须经过manager.get_task_queue()得到的Queue接口添加 
task = manager.get_task_queue()
result = manager.get_result_queue()
# 添加任务
for url in ['url_' + str(i) for i in range(10)]:
    print('put task %s...' % url)
    task.put(url)

# 获取返回结果
for i in range(10):
    print('result is %s' % result.get(timeout=10))
# 关闭管理
manager.shutdown()
print('master exit')

3 任务进程

任务进程主要的工做以下:分布式

  • 注册获取网络上queue
  • 链接服务器
  • 从task队列获取任务,并写入结果
    示例代码以下:
# -*- coding: utf-8 -*-

import time
from multiprocessing.managers import BaseManager

class QueueManager(BaseManager):
    """
    继承类BaseManager
    """
    pass

# 使用register注册,获取网络queue名称
QueueManager.register('get_task_queue')
QueueManager.register('get_result_queue')

# 配置服务器ip并链接服务器
server_addr = '127.0.0.1'
print('connect to server %s...' % server_addr)
m = QueueManager(address=(server_addr, 5000), authkey=b'abc')
# 从网络链接
m.connect()
# 获取queue对象
task = m.get_task_queue()
result = m.get_result_queue()
# 从task获取任务并将结果写入result
while(not task.empty()):
    image_url = task.get(True, timeout=5)
    print('run task download %s...' % image_url)
    time.sleep(1)
    result.put('%s ------>success' % image_url)
print('worker exit')

先启动服务进程,结果以下:ide

put task url_0...
put task url_1...
put task url_2...
put task url_3...
put task url_4...
put task url_5...
put task url_6...
put task url_7...
put task url_8...
put task url_9...

再启动任务进程,结果以下:网站

connect to server 127.0.0.1...
run task download url_0...
run task download url_1...
run task download url_2...
run task download url_3...
run task download url_4...
run task download url_5...
run task download url_6...
run task download url_7...
run task download url_8...
run task download url_9...
worker exit

再回过头来看服务进程端输出url

put task url_0...
put task url_1...
put task url_2...
put task url_3...
put task url_4...
put task url_5...
put task url_6...
put task url_7...
put task url_8...
put task url_9...
result is url_0 ------>success
result is url_1 ------>success
result is url_2 ------>success
result is url_3 ------>success
result is url_4 ------>success
result is url_5 ------>success
result is url_6 ------>success
result is url_7 ------>success
result is url_8 ------>success
result is url_9 ------>success
master exit

这个简单的分布式有什么用呢?从例子也能够看出,若是咱们设置多个任务进程,就能够把任务分配到多台机器上,服务端来添加url到队列,任务端来下载并返回结果。而Queue之因此能经过网络访问,就是经过QueueManager实现的。线程

相关文章
相关标签/搜索