我有一个Python Web应用程序,其中客户端(Ember.js)通过WebSocket与服务器通信(我使用Flask-SocketIO)。除了WebSocket服务器外,后端还执行两个值得一提的操作:
队列需要由多个核心处理,因此我不得不进行更改。
同时存在的问题:队列和线程库被Eventlet 猴子补丁,如果我停止使用经过猴子补丁的Thread和Queue并改用
现在我的问题是: 有没有办法让这个应用程序在单独的核心上执行OCR和图像转换? 如果可能的话,我想继续使用WebSocket和Eventlet。我拥有的优势是进程之间唯一的通信接口是队列。
我已经考虑过的想法: - 不使用Python实现的队列,而是使用I/O。例如,不同的子进程将访问专用Redis - 更进一步:将每个队列工作者作为单独的Python进程启动(例如python3 wsserver | python3 ocrqueue | python3 imgconvqueue)。然后我必须自己确保对队列和数据库的访问是非阻塞的。
最好的方法是保持单个进程,并使其与multiprocessing一起工作。
非常感谢您的帮助。
- 进行一些图像转换(使用graphicsmagick)
- 对来自客户端的图像进行OCR处理(使用tesseract)
当客户端提交图像时,它的实体将在数据库中创建,并将其ID放入图像转换队列中。工作线程会抓取并进行图像转换。之后,工作线程将其放入OCR队列中,由OCR队列工作线程处理。
到目前为止,WS请求在单独的线程中同步处理(Flask-SocketIO使用Eventlet进行处理),而重型计算操作则以异步方式发生(也在单独的线程中进行处理)。
现在问题来了:整个应用程序运行在树莓派3上。如果我不利用它的4个核心,我只有一个时钟频率为1.2 GHz的ARMv8核心。这对OCR来说非常弱。因此,我决定找出如何使用Python的多个核心。虽然我读到了关于GIL的问题,但我发现了multiprocessing,其中写道:多进程包同时提供本地和远程并发,通过使用子进程而不是线程有效地绕过全局解释器锁。
正是我想要的。所以我立即取代了
from threading import Thread
thread = Thread(target=heavy_computational_worker_thread)
thread.start()
通过
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()
同时存在的问题:队列和线程库被Eventlet 猴子补丁,如果我停止使用经过猴子补丁的Thread和Queue并改用
multiprocessing
中的版本,则由Eventlet启动的请求线程在访问队列时会永久阻塞。现在我的问题是: 有没有办法让这个应用程序在单独的核心上执行OCR和图像转换? 如果可能的话,我想继续使用WebSocket和Eventlet。我拥有的优势是进程之间唯一的通信接口是队列。
我已经考虑过的想法: - 不使用Python实现的队列,而是使用I/O。例如,不同的子进程将访问专用Redis - 更进一步:将每个队列工作者作为单独的Python进程启动(例如python3 wsserver | python3 ocrqueue | python3 imgconvqueue)。然后我必须自己确保对队列和数据库的访问是非阻塞的。
最好的方法是保持单个进程,并使其与multiprocessing一起工作。
非常感谢您的帮助。