我有一個Python web應用程序,客戶端(Ember.js)通過WebSocket與服務器通信(我使用的是Flask-SocketIO)。 除了網頁套接字服務器後端做兩兩件事,值得一提的:在Python和Eventlet中使用多核心
- 做一些圖像變換(使用graphicsmagick)
- OCR傳入圖像從客戶機(使用tesseract)
當客戶端提交圖像時,其實體將在數據庫中創建,並將該ID放入圖像轉換隊列中。工人抓住它並進行圖像轉換。之後,工作人員將其放入OCR隊列中,由OCR隊列工作人員處理。
到目前爲止這麼好。 WS請求在單獨的線程中同步處理(Flask-SocketIO爲此使用了Eventlet)並且繁重的計算操作異步發生(在單獨的線程中)。
現在的問題:整個應用程序運行在Raspberry Pi 3。如果我沒有使用4個內核,我只有一個ARMv8內核的主頻爲1.2 GHz。這對於OCR來說非常小。所以我決定找出如何在Python中使用多個核心。雖然我讀了關於GIL的問題),但我發現約multiprocessing它說The multiprocessing package offers both local and remote concurrency, effectively side-stepping the Global Interpreter Lock by using subprocesses instead of threads.
。正是我想要的。所以,我瞬間被
from multiprocessing import Process
process = Process(target=heavy_computational_worker_thread)
process.start()
需要進行,所以我不得不改變
from queue import Queue
queue = multiprocessing.Queue()
到
import multiprocessing
queue = multiprocessing.Queue()
由多個內核以及處理的隊列取代了
from threading import Thread
thread = Thread(target=heavy_computational_worker_thread)
thread.start()
。有問題:Eventlet的隊列和線程庫是monkey patched。如果我停止使用線程和隊列的Monkey修補版本並使用multiprocsssing
中的那個版本,則在訪問隊列時,由Eventlet啓動的請求線程永遠阻塞。
現在我的問題:
有什麼辦法可以讓這個應用程序做一個單獨的核心OCR和圖像轉換?
我想繼續使用WebSocket和Eventlet(如果可能的話)。我擁有的優勢是進程之間的唯一通信接口就是隊列。
我已經有的想法: - 不使用隊列的Python實現,而是使用I/O。例如,不同子進程可以訪問的專用Redis - 更進一步:將每個隊列工作者作爲單獨的Python進程啓動(例如,python3 wsserver | python3 ocrqueue | python3 imgconvqueue)。然後,我必須確保自己的隊列和數據庫上的訪問將是非阻塞的
儘管如此,最好的辦法是保持單個進程並使其與多處理工作。
非常感謝你提前
我不知道Evenlet庫,所以也許我的答案不適用。在「主」程序中使用多線程。在主應用程序的每個「Process」中,使用「subprocess」調用子程序(即使這看起來很奇怪,也可以調用python程序來調用python程序)。僅在這些子流程中使用「Eventlet」庫(或任何非流程安全庫)。不要在主程序中使用它們。您將無法使用「隊列」,但可以通過文件傳遞數據(例如:程序A寫入圖像文件然後終止,程序B啓動並讀取此文件)。 –