我有一个pythonweb应用程序,其中客户机(Ember.js)通过WebSocket与服务器通信(我使用的是Flask-SocketIO)。
除了WebSocket服务器,后端还做了两件值得一提的事情:OCR从客户端传入的图像(使用tesseract)
当客户机提交一个映像时,它的实体将在数据库中创建,并且id被放入一个映像转换队列中。工人抓起它并进行图像转换。之后,worker将它放入OCR队列,在那里它将由OCR队列worker处理。在
到目前为止还不错。WS请求在不同的线程中同步处理(Flask SocketIO为此使用Eventlet),而大量的计算操作是异步进行的(同样在不同的线程中)。在
现在的问题是:整个应用程序运行在一个树莓皮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 threading import Thread
thread = Thread(target=heavy_computational_worker_thread)
thread.start()
通过
^{pr2}$
队列也需要由多个核心处理,所以我不得不更改from queue import Queue
queue = multiprocessing.Queue()
到import multiprocessing
queue = multiprocessing.Queue()
还有。问题:队列和线程库是Eventlet的monkey patched。如果我停止使用线程和队列的monkey补丁版本,而使用来自multiprocsssing的版本,那么Eventlet启动的请求线程在访问队列时永远阻塞。在
现在我的问题是:
有没有办法让这个应用程序在单独的内核上进行OCR和图像转换?
如果可能的话,我想继续使用WebSocket和Eventlet。我的优点是进程之间唯一的通信接口是队列。在
我已有的想法:
-不是使用队列的Python实现,而是使用I/O。例如,不同子进程将访问的专用Redis
-更进一步:将每个队列工作进程作为单独的Python进程启动(例如python3wsserver | python3ocrqueue | python3imgconvqueue)。然后我必须确保对队列和数据库的访问是非阻塞的
不过,最好的办法是保持单个进程,并使其与多进程一起工作。在
事先非常感谢