zoukankan      html  css  js  c++  java
  • 分布式 task_master / task_worker

    17:08:0317:08:04

    在Thread(线程)和Process(进程)中,应当优选Process,因为Process更稳定,而且,Process可以分布到多台机器上,而Thread最多只能分布到同一台机器的多个CPU上。

    Python的multiprocessing模块不但支持多进程,其中managers子模块还支持把多进程分布到多台机器上。

    一个服务进程可以作为调度者(master),将任务分布到其他多个进程中,依靠网络通信。由于managers模块封装很好,不必了解网络通信的细节,就可以很容易地编写分布式多进程程序。


    master/worker 方法已经封装了socket模块,在其他用途中绝大部分代码是直接使用的...(Python是思路、方法都高度统一的)

     注:win环境下master和worker不能再IDE中直接打开,只能在DOS中打开

    master主机

    #coding=utf-8
    # tast_master.py
    '''
    我们先看服务进程,服务进程负责启动Queue,把Queue注册到网络上,然后往Queue里面写入任务
    '''
    import random, time, queue
    from multiprocessing import freeze_support
    from multiprocessing.managers import BaseManager
    
    # 发送任务的队列:
    task_queue = queue.Queue()
    # 接收结果的队列:
    result_queue = queue.Queue()
    
    # 从BaseManager继承的QueueManager:
    class QueueManager(BaseManager):
        pass
    
    def return_task_queue():
        global task_queue
        return task_queue
     
    def return_result_queue():
        global result_queue
        return result_queue
    # 把两个Queue都注册到网络上, callable参数关联了Queue对象:
    if __name__=="__main__":
        #如果你的机器是win32,Run code for process object if this in not the main process
        freeze_support()
        '''
        请注意,当我们在一台机器上写多进程程序时,创建的Queue可以直接拿来用,
        但是,在分布式多进程环境下,添加任务到Queue不可以直接对原始的
        task_queue进行操作,那样就绕过了QueueManager的封装,必须通过
        manager.get_task_queue()获得的Queue接口添加。
        '''
        QueueManager.register('get_task_queue', callable=return_task_queue)
        QueueManager.register('get_result_queue', callable=return_result_queue)
        # 绑定端口5000, 设置验证码'abc':
        manager = QueueManager(address=('127.0.0.1', 5000), authkey=b'abc')
        # 启动Queue:
        manager.start()
        # 获得通过网络访问的Queue对象:
        task = manager.get_task_queue()
        result = manager.get_result_queue()
        # 放几个任务进去:
        for i in range(10):
            n = random.randint(0, 10000)
            print('Put task %d...' % n)
            task.put(n)
        # 从result队列读取结果:
        print('Try get results...')
        for i in range(10):
            r = result.get(timeout=20)
            print('Result: %s' % r)
        # 关闭:
        manager.shutdown()
        print('master exit.')

    worker

    #coding=utf-8
    # tast_worker.py
    
    import time, sys, queue
    
    from multiprocessing.managers import BaseManager
    
    # 创建类似的QueueManager:
    class QueueManager(BaseManager):
        pass
    
    # 由于这个QueueManager只从网络上获取Queue,所以注册时只提供名字:
    QueueManager.register('get_task_queue')
    QueueManager.register('get_result_queue')
    
    # 连接到服务器,也就是运行task_master.py的机器:
    server_addr = '127.0.0.1'
    print('Connect to server %s...' % server_addr)
    # 端口和验证码注意保持与task_master.py设置的完全一致:
    m = QueueManager(address=(server_addr, 5000), authkey=b'abc')
    # 从网络连接:
    m.connect()
    # 获取Queue的对象:
    task = m.get_task_queue()
    result = m.get_result_queue()
    # 从task队列取任务,并把结果写入result队列:
    for i in range(10):
        try:
            n = task.get(timeout=1)
            print('run task %d * %d...' % (n, n))
            r = '%d * %d = %d' % (n, n, n*n)
            time.sleep(1)
            result.put(r)
        except Queue.Empty:
            print('task queue is empty.')
    # 处理结束:
    print('worker exit.')
  • 相关阅读:
    dubbo开发中使用到的一些服务配置方式
    jedis连接池详解(Redis)
    《Java线程池》:任务拒绝策略
    BlockingQueue(阻塞队列)详解
    洛谷 P3275 BZOJ 2330 [SCOI2011]糖果
    LaTeX的简单使用方法
    洛谷 P1131 BZOJ 1060 [ZJOI2007]时态同步
    洛谷 P2587 BZOJ 1034 [ZJOI2008]泡泡堂
    苦酒入喉心作痛,红酒入鹅鹅想哭——震惊!勒索病毒想哭靠wine感染了Ubuntu16.04
    洛谷 P2144 BZOJ 1003 [FJOI2007]轮状病毒
  • 原文地址:https://www.cnblogs.com/hellangels333/p/8177899.html
Copyright © 2011-2022 走看看