1、概念
分布式进程指的是将Process进程分布到多台机器上,充分利用多台机器的性能完成复杂的任务。
multiprocessing模块不仅支持多进程,而且其中的managers模块还支持把多进程分布到多台机器上。例如,写一个服务进程作为调度者,将任务分布到其他多个进程中,依靠网络通信(将Queue暴露到网络中,实现本地队列的网络化)进行管理。
2、步骤
2.1 服务进程的创建
1、建立队列Queue,用来进行进程间的通信。
(1)服务进程创建任务队列task_queue,用来作为传递任务给任务进程的通道
(2)服务进程创建结果队列result_queue,用来作为任务进程完成任务后回复服务进程的通道
2、把创建的队列在网络上注册,暴露给其他进程
(1)通过multiprocessing.managers.BaseManage.register创建Queue接口来作为添加任务的通道,typeid是调用的方法名,callable是绑定的本地获取Queue的方法
3、创建一个对象(multiprocessing.managers.BaseManage)的实例manager,绑定端口和验证口令
(1)通过multiprocessing.managers.BaseManage绑定本地端口,指定authkey,authkey接受bytes类型
4、启动manager,开始监听信息通道
(1)manager.start()
5、通过管理实例的方法(第2步中注册的typeid的参数)获得通过网络访问的Queue对象,即再把网络队列实例化成可以使用的本地队列
(1)task = manager.get_task_queue()
6、创建任务到本地队列中,会自动上传到网络队列中,分配给任务进程去处理
(1)task.put()
7、关闭实例manager
(1)manager.shutdown()
8、示例代码
# 示例代码来自《Python爬虫开发与项目实战》,作者范传辉 from multiprocessing.managers import BaseManager import queue # 创建队列 task_queue = queue.Queue() result_queue = queue.Queue() # 注册方法,在网络上暴露队列 # QueueManager.register(typeid="get_task_queue", callable=lambda: task_queue) # QueueManager.register(typeid='get_result_queue', callable=lambda: result_queue) BaseManager.register(typeid="get_task_queue", callable=lambda: task_queue) BaseManager.register(typeid='get_result_queue', callable=lambda: result_queue) # 创建本例manager实例 address = ('127.0.0.1', 8001) # manager = QueueManager(address=address, authkey=b'biu') manager = BaseManager(address=address, authkey=b'biu') # 启动 manager.start() # 通过管理实例的方法获得通过网络访问的Queue对象 task = manager.get_task_queue() result = manager.get_result_queue() # 添加任务 for url in ["image_url_" + str(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 in %s ' % result.get(timeout=10)) manager.shutdown()
2.2 任务进程的创建
1、使用multiprocessing.managers.BaseManager注册用于获取Queue的方法名称(任务进程只能通过名称来在网络上获取Queue)
(1)BaseManger.register(typeid='get_task_queue')
2、连接服务器,端口和验证口令要与服务进程完全一致
(1)创建manager实例:manager = BaseManager(address=address,authkey=b'...')
(2)连接服务器:manager.connect()
3、本地化网络队列
(1)task = manager.get_task_queue()
4、从任务队列获取任务,将结果写入result队列
5、实例代码
# 示例代码来自《Python爬虫开发与项目实战》,作者范传辉 import time from multiprocessing.managers import BaseManager # 注册用于获取queue的方法名称 BaseManager.register(typeid='get_task_queue') BaseManager.register(typeid='get_result_queue') # 连接到服务器 server_addr = ('127.0.0.1', 8001) print("connect to server %s" % str(server_addr)) manager = BaseManager(address=server_addr, authkey=b'biu') manager.connect() # 获取queue对象 task = manager.get_task_queue() result = manager.get_result_queue() 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')