У меня есть веб-приложение Python, в котором клиент (Ember.js) взаимодействует с сервером через WebSocket (я использую Flask-SocketIO). Помимо сервера WebSocket, бэкэнд делает еще две вещи, о которых стоит упомянуть:
- Преобразование изображений (используя graphicsmagick)
- Распознавание входящих изображений от клиента (с использованием tesseract)
Когда клиент отправляет изображение, его сущность создается в базе данных, а идентификатор помещается в очередь преобразования изображения. Рабочий берет его и выполняет преобразование изображения. После этого обработчик помещает его в очередь OCR, где он будет обрабатываться обработчиком очереди OCR.
Все идет нормально. Запросы WS обрабатываются синхронно в отдельных потоках (Flask-SocketIO использует для этого Eventlet), а тяжелые вычислительные действия выполняются асинхронно (также в отдельных потоках).
Теперь проблема: все приложение работает на Raspberry Pi 3. Если я не использую 4 ядра, у меня есть только одно ядро ARMv8 с тактовой частотой 1,2 ГГц. Это очень маленькая мощность для 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()
by
from multiprocessing import Process
process = Process(target=heavy_computational_worker_thread)
process.start()
Очередь также должна была обрабатываться несколькими ядрами, поэтому мне пришлось изменить
from queue import Queue
queue = multiprocessing.Queue()
to
import multiprocessing
queue = multiprocessing.Queue()
также. Проблема: очередь и библиотеки потоков обезьяны исправлены с помощью Eventlet. Если я перестану использовать исправленную обезьяной версию Thread и Queue и вместо этого буду использовать версию из multiprocsssing
, то поток запроса, запущенный Eventlet, навсегда заблокируется при доступе к очереди.
Теперь мой вопрос:
Можно ли как-нибудь заставить это приложение выполнять распознавание символов и преобразование изображений на отдельном ядре?
Я хотел бы продолжать использовать WebSocket и Eventlet, если это возможно. Преимущество, которое у меня есть, заключается в том, что единственным интерфейсом связи между процессами будет очередь.
Идеи, которые у меня уже были: - Не использовать реализацию очереди на Python, а использовать ввод-вывод. Например, выделенный Redis, к которому будут обращаться различные подпроцессы. Идем дальше: запускаем каждый обработчик очереди как отдельный процесс Python (например, python3 wsserver | python3 ocrqueue | python3 imgconvqueue). Тогда я должен был бы сам убедиться, что доступ к очереди и к базе данных будет неблокирующим.
Однако лучше всего было бы сохранить один процесс и заставить его работать с многопроцессорной обработкой.
заранее большое спасибо