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')