分部式进程是指将Process进程分布到多台机器上,充分利用多台机器的性能完成复杂的任务。
分布式进程在Python中依然要用到multiprocessing模块。multiprocessing模块不但支持多进程,其中managers子模块还支持把多进程分布到多台机器上。可以写一个服务进程作为调度者,将任务分布到其他多个进程中,依靠网络通信进行管理。
创建分布式进程的步骤:
1、建立队列Queue,用来进行进程间的通信。服务进程创建任务队列task_queue,用来作为传递任务给任务进程的通道;服务进程创建结果队列result_queue,作为任务进程完成任务后回复服务进程的通道。在分布式多进程环境下,必须通过由Queuemanager获得的Queue接口来添加任务。
2、把第一步中建立的队列在网络上注册,暴露给其他进程(主机),注册后获得网络队列,相当于本地队列的映像。
3、建立一个对象(Queuemanager(BaseManager))实例manager,绑定端口和验证口令。
4、启动第三步中建立的实例,即启动管理manager,监管信息通道。
5、通过管理实例的方法获得通过网络访问的Queue对象,即再把网络队列实体化成可以使用的本地队列。
6、创建任务到“本地”队列中,自动上传任务到网络队列中,分配给任务进程进行处理。
例子:
import random import time from multiprocessing.managers import BaseManager from queue import Queue # 第一建立队列用来存放任务和结果 task_queue = Queue() result_queue = Queue() class Queuemanager(BaseManager): pass # 第二步注册队列在网络,利用register方法,callable参数关联Queue对象,将Queue对象在网络中暴露 Queuemanager.register('get_task_queue', callable=lambda: task_queue) Queuemanager.register('get_result_queue', callable=lambda: result_queue) # 第三步绑定端口8001,设置验证口令 manager = Queuemanager(address=('', 8001), authkey='vfast') # 第四步启动管理,监听信息通道 manager.start() # 第五步通过管理实例的方法获得通过网络访问的Queue对象 task = manager.get_task_queue() result = manager.get_result_queue() # 第六步添加任务 for url in ['ImageUrl_' + i for i in range(10)]: print('put task %s ...' % url) task.put(url) # 获取返回结果 print('try get result ...') for i in range(10): print('result is %s ' % result.get(timeout=10)) # 关闭管理 manager.shutdown()
任务进程步骤:
1、使用QueueManager注册用于获取Queue的方法名称,任务进程只能通过名称在网络上获取Queue
2、连接服务器,端口和验证口令注意保持与服务进程中完全一致。
3、从网络上获取Queue,进行本地化
4、从task队列获取任务,并把结果写入result队列
例子:
import time from multiprocessing.managers import BaseManager class QueueManager(BaseManager): pass # 等一步使用QueueManager注册用于获取Queue的方法名称 QueueManager.register('get_task_queue') QueueManager.register('get_result_queue') # 第二步连接服务器 server_addr = '127.0.0.1' print('Connect to server %s ...' % server_addr) # 端口和验证口令保持与服务进程一致 m = QueueManager(address=(server_addr, 8001), authkey='vfast') # 从网络连接 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.')
来源:Python爬虫开发与项目实战