在Python和Eventlet中使用多个核心

Sch*_*ken 5 python multithreading multiprocessing eventlet flask-socketio

我有一个Python Web应用程序,客户端(Ember.js)通过WebSocket与服务器通信(我正在使用Flask-SocketIO).除了WebSocket服务器之外,后端还有两件值得提及的事情:

当客户端提交图像时,在数据库中创建其实体,并将id放入图像转换队列中.工人抓住它并进行图像转换.之后,工作人员将其放入OCR队列,在那里它将由OCR队列工作者处理.

到现在为止还挺好.WS请求在不同的线程中同步处理(Flask-SocketIO使用Eventlet),并且繁重的计算操作异步发生(在单独的线程中也是如此).

现在问题是:整个应用程序在Raspberry Pi 3上运行.如果我没有使用它的4核,我只有一个主频为1.2 GHz的ARMv8内核.这对于OCR来说是非常小的力量.所以我决定了解如何在Python中使用多个内核.虽然我读到了GIL的问题但是我发现了多处理的地方The multiprocessing package offers both local and remote concurrency, effectively side-stepping the Global Interpreter Lock by using subprocesses instead of threads..正是我想要的.所以我立即取代了

from threading import Thread
thread = Thread(target=heavy_computational_worker_thread)
thread.start()
Run Code Online (Sandbox Code Playgroud)

通过

from multiprocessing import Process
process = Process(target=heavy_computational_worker_thread)
process.start()
Run Code Online (Sandbox Code Playgroud)

队列需要由多个核心处理,所以我不得不改变

from queue import Queue
queue = multiprocessing.Queue()
Run Code Online (Sandbox Code Playgroud)

import multiprocessing
queue = multiprocessing.Queue()
Run Code Online (Sandbox Code Playgroud)

同样.有问题:队列和线程库由Eventlet 进行猴子修补.如果我停止使用猴子修补版本的Thread和Queue并使用相应的那个,multiprocsssing那么在访问队列时,Eventlet启动的请求线程会永久阻塞.

现在我的问题:

有什么办法可以让这个应用程序在单独的核心上进行OCR和图像转换吗?

如果可能的话,我想继续使用WebSocket和Eventlet.我的优点是进程之间唯一的通信接口是队列.

我已经拥有的想法: - 不使用队列的Python实现,而是使用I/O. 例如,不同子进程可以访问的专用Redis - 更进一步:将每个队列工作者作为单独的Python进程启动(例如python3 wsserver | python3 ocrqueue | python3 imgconvqueue).然后我必须确保自己对队列和数据库的访问是非阻塞的

但最好的办法是保持单个进程并使其与多处理一起工作.

非常感谢你提前

Mig*_*uel 5

Eventlet 目前与多处理包不兼容。这项工作有一个未解决的问题:https ://github.com/eventlet/eventlet/issues/210 。

我认为适合您的情况的另一种选择是使用 Celery 来管理您的队列。Celery 将启动一个工作进程池,等待主进程通过消息队列提供的任务(RabbitMQ 和 Redis 都支持)。

Celery 工作线程不需要使用 eventlet,只有主服务器才需要,因此这可以让他们自由地做任何他们需要做的事情,而不受 eventlet 强加的限制。

如果您有兴趣探索这种方法,我有一个使用它的完整示例: https: //github.com/miguelgrinberg/flack