python进程间通信(二)-分布式进程

Python的multiprocessing模块不但支持多进程,其中managers子模块还支持把多进程分布到多台机器上.一个服务进程可以作为调度者,将任务分布到其他多个进程中,依靠网络通信.由于managers模块封装把网络通信的都给封装好了,所以即使我们不了解网络通信,也能写出分布式多进程程序.

为什么使用分布式进程

如果我们的一个通过Queue通信的多进程程序在一台机器上运行.随着要处理的任务越来越繁重,甚至一台机器根本都没法完成了.我们能想到什么?肯定是想到把这些任务分发到多台机器上来做了,这样的话,就需要使用分布式进程了.

如何实现

实现其实不难.原有的Queue继续使用,然后通过managers模块, 在master节点把Queue注册到网络中,worker节点就可以访问到注册在网络中的Queue了。
看下面的案例:
master节点代码

# task.py
from multiprocessing.managers import BaseManager
from multiprocessing import Process, Queue

import time


class Master(object):

    # 创建一个分布式管理器
    def start_Manager(self,member_q,result_q):
        # 把创建的两个队列注册在网络上,利用register方法,callable参数关联了Queue对象,
        # 将Queue对象在网络中暴露

        BaseManager.register('get_task_queue',callable=lambda:member_q)
        BaseManager.register('get_result_queue',callable=lambda:result_q)
  // 地址使用master端的地址
        manager = BaseManager(address=('', 5000), authkey='abc'.encode('utf-8'))
        return manager
    
    def put(self, member_q, result_q):
        i = 0
        while True:
            
            string = "写入数据_%s" % i
            print string
            member_q.put(string)
            i += 1
            time.sleep(1)
            
    def get(self, member_q, result_q):
        while True:
            if not result_q.empty():
                result = result_q.get()
                print "result队列读出结果:%s" %result
                time.sleep(1)
            else:
                time.sleep(1)
                
if __name__ == "__main__":
   
    member_q = Queue()
    result_q = Queue()
    
    #创建分布式管理器
    node = Master()
    manager = node.start_Manager(member_q,result_q)

    # manager.start()
    // 创建两个进程多和写queue队列的数据
    p_put = Process(target=node.put, args=(member_q, result_q,))
    p_get = Process(target=node.get, args=(member_q, result_q,))
    p_get.start()
    p_put.start()
    
    # p_put.join()
    # p_get.join()
    // 开启服务
    manager.get_server().serve_forever()
    # manager.shutdown()
        

worker节点

# coding:utf-8

import time
from multiprocessing.managers import BaseManager


class Node(object):
    # 初始化分布式进程中的工作节点的连接工作
    def __init__(self):
        BaseManager.register('get_task_queue')
        BaseManager.register('get_result_queue')
        // 地址使用master端的地址
        server_addr = '127.0.0.1'
        print(('Connect to server %s...' % server_addr))
        self.m = BaseManager(address=(server_addr, 5000), authkey='abc'.encode('utf-8'))
        self.m.connect()
        
        # 获取在网络中注册的Queue的对象:
        self.task = self.m.get_task_queue()
        self.result = self.m.get_result_queue()
        
        
    def work(self):
        while True:
            try:
                if not self.task.empty():
                    t = self.task.get()
                    print "队列中取出数据:",t
                    time.sleep(0.5)
                else:
                    print "task队列为空"
                    time.sleep(1)
                    
                s = "返回结果"
                self.result.put(s)
                
            except EOFError as e:
                print("连接工作节点失败")
                return
            except Exception as e:
                print(e)
                print('Crawl fail ')

if __name__ == "__main__":
    n = Node()
    n.work()

这样的话,在master节点写进Queue队列中的数据,在worker节点可以读取到,同时,worker节点也可以向Queue队列写数据,同样,在master端也可以读到worker节点写的数据.
实际上,我们的爬虫就可以我们可以利用以上通信方式,开发出分布式爬虫.后续会把利用此开发的分布式爬虫共享一下.

猜你喜欢

转载自blog.csdn.net/weixin_35762183/article/details/88638054
今日推荐