首页 > 解决方案 > Flask-SocketIO - 如何从子进程发出事件

问题描述

我有一个 Flask 应用程序,它在某些休息调用时使用 ProcessPoolExecutor 运行几个模块。

更新:添加redis作为消息队列(使用docker,redis作为redis的主机)

socketio = SocketIO(app, message_queue='redis://redis')

(...)

def emit_event(evt, message):
    socketio.emit(evt, message, namespace='/test')

@app.route('/info', methods=['GET'])
def info():
    emit_event('update_reports', '')

(...)
if __name__ == "__main__":
    socketio.run(host='0.0.0.0', threaded=True)

现在我添加了 redis,它在从主应用程序发射时仍然有效。这里有一些我正在运行子进程的代码:

def __init__(self):
    self.executor = futures.ProcessPoolExecutor(max_workers=4)
    self.socketio = SocketIO(async_mode='eventlet', message_queue='redis://redis')

    (...)
    future = self.executor.submit(process, params)
    future.add_done_callback(functools.partial(self.finished_callback, pid))

然后在那个回调中我调用emit_event方法:

def finished_callback(self, pid, future):
    pid.status = Status.DONE.value
    pid.finished_at = datetime.datetime.utcnow
    pid.save()

    self.socketio.emit('update_reports', 'done', namespace='/test')

从我的控制器向客户端获取和发送/发送消息工作得很好,如果我从 curl 或邮递员调用 /info 我的客户端会收到消息 - 但是 - 当尝试从这个子进程回调中以相同的方式发出事件时,现在它显示此错误:

这主要用于通知,例如通知一个漫长的过程何时完成等等。

INFO:socketio:emitting event "update_reports" to all [/test] ERROR:socketio:Cannot publish to redis... retrying ERROR:socketio:Cannot publish to redis... giving up

我做错了什么?

谢谢!

标签: python-3.xflasksocket.ioflask-socketio

解决方案


在设置 Flask-SocketIO 扩展时需要遵循一些特定规则,以便外部进程可以发出,其中包括使用主进程和外部进程用来协调工作的消息队列。有关说明,请参阅文档的从外部进程发出部分。


推荐阅读