繁体   English   中英

Python multiprocessing.managers.BaseManager依次运行已注册的可调用函数

[英]Python multiprocessing.managers.BaseManager running registered callable function sequentially

我正在使用Python的多处理库提供的远程管理器。 我已经使用BaseManager设置了一个远程服务器,多个客户端同时连接到该服务器。 不幸的是,我的服务器正在按顺序为每个客户端提供请求。 我的服务器应该通过网络调用Google的Directions API来返回距离和时间。

我的理解是,将为每个连接的客户端生成一个新线程,因此我不会遇到此问题。

我以简化的方式提供了代码示例。

这是服务器代码:

import time
from multiprocessing.managers import BaseManager
import threading

class DistanceTime:

    def get_distance_time(self):
        print('started by thread %s'%(threading.get_ident()))
        # assume that network request was made here
        time.sleep(2)
        print('ended by thread %s'%(threading.get_ident()))

def server():
    distance_time=DistanceTime()
    BaseManager.register('get_distance_time', callable=distance_time.get_distance_time)
    manager = BaseManager(address=('localhost', 5000), authkey=b'abracadabra')
    server = manager.get_server()
    print('server running')
    server.serve_forever()

server()

这是客户端代码:

from multiprocessing.managers import BaseManager
from concurrent.futures import ThreadPoolExecutor
import time

def client():
    BaseManager.register('get_distance_time')
    manager = BaseManager(address=('localhost', 5000), authkey=b'abracadabra')
    manager.connect()
    executor = ThreadPoolExecutor(max_workers=3)
    # client mades three simultaneous requests to the server
    b=executor.submit(manager.get_distance_time)
    b=executor.submit(manager.get_distance_time)
    c=executor.submit(manager.get_distance_time)
    print('done')
    time.sleep(5)

client()

即使客户端立即发送所有三个请求,服务器也会打印以下内容:

server running
started by thread 16740
ended by thread 16740
started by thread 4712
ended by thread 4712
started by thread 7132
ended by thread 7132

理想情况下,所有开始的打印件都应该放在一起。 这是我的应用程序的主要瓶颈。

您正在register的可调用对象是“创建”方法,它们始终在锁定的上下文中运行 ,但是它返回的对象将自动被代理,并且对其调用的任何方法都不会被自动锁定

在您的演示代码中,我将更改:

def server():
    distance_time=DistanceTime()
    BaseManager.register('get_distance_time', callable=distance_time.get_distance_time)

成为:

def server():
    distance_time = DistanceTime()
    BaseManager.register('DistanceTime', lambda: distance_time)

然后将其用作:

distance_time = manager.DistanceTime()
a = executor.submit(distance_time.get_distance_time)
b = executor.submit(distance_time.get_distance_time)
c = executor.submit(distance_time.get_distance_time)

这应该允许一切并行进行。 我没有实际测试过,但是如果您说这行不通的话...

并不是说这里很重要,但我通常认为最好将这些内容注册在单独的/派生的Manager

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM