![](/img/trans.png)
[英]Broken Pipe when Using Python Multiprocessing Managers (BaseManager/SyncManager) to Share Queue with Remote Machines
[英]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.