Я в ситуации, когда получаю сообщение от клиента. Внутри функции, которая обрабатывает этот запрос (@socketio.on), я хочу вызвать функцию, где выполняется какая-то тяжелая работа. Это не должно приводить к блокировке основного потока, и считается, что клиент будет проинформирован после завершения работы. Таким образом, я запускаю новый поток.
Теперь я сталкиваюсь с действительно странным поведением: Сообщение никогда не доходит до клиента. Однако код достигает этого места, где отправляется сообщение. Еще более удивительным является тот факт, что если в потоке ничего не происходит, кроме сообщения, отправляемого клиенту, тогда ответ на самом деле находит свой путь к клиенту.
Подводя итог: Если что-то вычислительно интенсивно происходит до отправки сообщения, оно не доставляется, иначе оно есть.
Как говорится здесь и здесь, отправка сообщений от потока к клиентам не является проблемой вообще:
Во всех примерах, показанных до этого момента, сервер отвечает на событие, отправленное клиентом. Но для некоторых приложений сервер должен быть инициатором сообщения. Это может быть полезно для отправки уведомлений клиентам о событиях, возникших на сервере, например, в фоновом потоке.
Вот пример кода. При удалении комментариев (*) сообщение ('foo from thread') не находит своего пути к клиенту, в противном случае это делает.
from flask import Flask
from flask.ext.socketio import SocketIO, emit
app = Flask(__name__)
socketio = SocketIO(app)
from threading import Thread
import time
@socketio.on('client command')
def response(data):
thread = Thread(target = testThreadFunction)
thread.daemon = True
thread.start()
emit('client response', ['foo'])
def testThreadFunction():
# time.sleep(1)
socketio.emit('client response', ['foo from thread'])
socketio.run(app)
Я использую Python 3.4.3, Flask 0.10.1, flask-socketio1.2, eventlet 0.17.4.
Этот образец может быть скопирован и вставлен в .py файл, и поведение может быть немедленно воспроизведено.
Может кто-нибудь объяснить это странное поведение?
Обновление
Кажется, это ошибка в eventlet. Если я это сделаю:
socketio = SocketIO(app, async_mode='threading')
Это заставляет приложение не использовать флажок, хотя он установлен.
Однако это не применимое решение для меня, как использование "threading", поскольку async_mode отказывается принимать двоичные данные. Каждый раз, когда я отправляю некоторые двоичные данные от клиента на сервер, он говорит:
WebSocket transport not available. Install eventlet or gevent and gevent-websocket for improved performance.
Третий вариант: использование gevent async_mode для меня не работает, а gevent еще не поддерживает python 3.
Итак, любые другие предложения?