Как я могу одновременно использовать транспорт Websocket и async_mode=threading в flask-socketio?

Я настраиваю сервер socket.io, и у нас есть несколько фоновых потоков, которые вызывают длинные блокирующие методы, которые опрашивают данные. Мы также хотим передавать данные клиенту socket.io из этих потоков. Мы столкнулись с проблемами, когда эти потоки что-то выдавали, и это занимало целую вечность, пока это не было передано клиентам, пока мы не переключились на async_mode='threading'. Тогда все работало отлично, за исключением того, что теперь мы получаем предупреждение:

Транспорт WebSocket недоступен. Установите eventlet или gevent и gevent-websocket для повышения производительности.

Эти модули установлены, но не используются в многопоточном режиме. Как мы можем иметь оба фоновых потока, которые всегда работают и не вызывают socketio.sleep, и в то же время использовать транспорт Websocket вместо потоковой передачи? Спасибо


person C. Dill    schedule 15.05.2019    source источник


Ответы (1)


Я автор Flask-SocketIO и сервера Socket.IO, на котором он построен.

Короткий ответ: вам нужен кто-то, кто добавит автономную поддержку WebSocket в пакет python-engineio, одну из основных зависимостей Flask-SocketIO.

Вот длинный ответ. Сервер WebSocket на основе стандартных потоков — вообще плохая идея, поэтому я никогда не реализовывал его сам. Серверы WebSocket очень требовательны, потому что требуют постоянного соединения с каждым клиентом. Если у вас есть 100 подключенных клиентов, вам нужно 100 активных подключений. В многопоточном сервере это означает, что вам нужно 100 потоков, работающих одновременно, и в течение потенциально длительного времени. К сожалению, количество потоков, которые вы можете иметь в процессе Python, несколько ограничено. Вы, вероятно, можете иметь 100, но 1000 может быть проблемой. Почти во всех реализациях WebSocket используются асинхронные серверы, потому что этот тип сервера может легко поддерживать большое количество активных подключений.

Надеюсь, это дает вам обоснование того, почему я никогда не реализовывал WebSocket для потоков. С учетом сказанного, для серверов с небольшим количеством клиентов поток на клиента может быть приемлемым, поэтому я готов добавить эту функциональность, если кто-то решит реализовать ее и внести свой вклад.

person Miguel    schedule 16.05.2019
comment
Спасибо за ваш вдумчивый ответ. Не обязательно иметь один поток для каждого клиента, но мы хотим, чтобы всегда было несколько потоков, опрашивающих данные в фоновом режиме и затем передающих результаты каждому клиенту. Есть ли способ использовать eventlet или gevent, но при этом иметь другие потоки, не связанные с циклом событий? Можем ли мы указать socketio читать из очереди, в которую записываются другие потоки, и периодически выдавать данные из этой очереди? Должны ли мы использовать внешнюю зависимость, такую ​​как Redis? Спасибо - person C. Dill; 16.05.2019
comment
Связь между потоком событий и другими потоками затруднена, потому что для того, чтобы это было эффективно, это должно быть сделано неблокирующим способом. Eventlet поддерживает наличие пула рабочих потоков, в которые можно отправлять задания. См. eventlet.net/doc/threading.html для получения дополнительной информации об этой функции. - person Miguel; 17.05.2019