簡體   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