gunicorn多进程启动,flask-socketio通信问题

首先必须要感谢一下辉哥的书,  先就这么称呼吧,哈哈.
感谢把我带入flask的大门,非常感谢.
最近碰到个问题, 我使用了flask-socketio, 使用gunicorn这个部署的flask.
后台使用emit发送消息的时候, 前端有时候能接到消息,有时候不能收到消息.
经过调试输入current_app的id值,结果这个值在不断的变化.
只有当前current_app是与websocketio建立连接的app时,发送消息才会成功.
以单个进程方式启动此时就没有问题了. 但是我想以多个进程方式运行,我现在还不知道该怎么处理.
希望碰到过这方面问题的朋友指点一二, 不胜感激.

3个进程启动输出信息如下:
gunicorn -w 3 --thread 3 --log-level=DEBUG --worker-class eventlet app:app
[2019-04-04 10:08:29 +0800] [109171] [DEBUG] POST /start_game
'start_game(), current_app: 140032880716752'
[2019-04-04 10:08:29 +0800] [109171] [DEBUG] Closing connection. 
[2019-04-04 10:08:30 +0800] [109169] [DEBUG] POST /report_start_game
'report_start_game(), current_app: 140032880712368'
[2019-04-04 10:08:30 +0800] [109169] [DEBUG] Closing connection. 
[2019-04-04 10:08:32 +0800] [109169] [DEBUG] POST /start_game
'start_game(), current_app: 140032880712368'
[2019-04-04 10:08:32 +0800] [109169] [DEBUG] Closing connection. 
[2019-04-04 10:08:33 +0800] [109173] [DEBUG] POST /report_start_game
'report_start_game(), current_app: 140032880717040'
[2019-04-04 10:08:33 +0800] [109173] [DEBUG] Closing connection. 
[2019-04-04 10:08:35 +0800] [109173] [DEBUG] POST /start_game
'start_game(), current_app: 140032880717040'
[2019-04-04 10:08:35 +0800] [109173] [DEBUG] Closing connection. 
[2019-04-04 10:08:36 +0800] [109169] [DEBUG] POST /report_start_game
'report_start_game(), current_app: 140032880712368'
[2019-04-04 10:08:36 +0800] [109169] [DEBUG] Closing connection. 
[2019-04-04 10:08:37 +0800] [109173] [DEBUG] POST /start_game
'start_game(), current_app: 140032880717040'
[2019-04-04 10:08:37 +0800] [109173] [DEBUG] Closing connection. 
[2019-04-04 10:08:37 +0800] [109169] [DEBUG] POST /report_start_game
'report_start_game(), current_app: 140032880712368'
[2019-04-04 10:08:37 +0800] [109169] [DEBUG] Closing connection. 
[2019-04-04 10:08:39 +0800] [109169] [DEBUG] POST /start_game
'start_game(), current_app: 140032880712368'
[2019-04-04 10:08:39 +0800] [109169] [DEBUG] Closing connection. 
[2019-04-04 10:08:39 +0800] [109173] [DEBUG] POST /report_start_game
'report_start_game(), current_app: 140032880717040'
[2019-04-04 10:08:39 +0800] [109173] [DEBUG] Closing connection. 
[2019-04-04 10:08:41 +0800] [109171] [DEBUG] POST /start_game
'start_game(), current_app: 140032880716752'
[2019-04-04 10:08:41 +0800] [109171] [DEBUG] Closing connection. 
[2019-04-04 10:08:41 +0800] [109171] [DEBUG] POST /report_start_game
'report_start_game(), current_app: 140032880716752'
[2019-04-04 10:08:41 +0800] [109171] [DEBUG] Closing connection. 
单个进程启动输出信息如下
gunicorn -w 1 --thread 3 --log-level=DEBUG --worker-class eventlet app:app
[2019-04-04 10:10:59 +0800] [109420] [DEBUG] POST /start_game
'start_game(), current_app: 139984677481136'
[2019-04-04 10:10:59 +0800] [109420] [DEBUG] Closing connection. 
[2019-04-04 10:10:59 +0800] [109420] [DEBUG] POST /report_start_game
'report_start_game(), current_app: 139984677481136'
[2019-04-04 10:10:59 +0800] [109420] [DEBUG] Closing connection. 
[2019-04-04 10:11:00 +0800] [109420] [DEBUG] POST /start_game
'start_game(), current_app: 139984677481136'
[2019-04-04 10:11:00 +0800] [109420] [DEBUG] Closing connection. 
[2019-04-04 10:11:01 +0800] [109420] [DEBUG] POST /report_start_game
'report_start_game(), current_app: 139984677481136'
[2019-04-04 10:11:01 +0800] [109420] [DEBUG] Closing connection. 
[2019-04-04 10:11:01 +0800] [109420] [DEBUG] POST /start_game
'start_game(), current_app: 139984677481136'
[2019-04-04 10:11:01 +0800] [109420] [DEBUG] Closing connection. 
[2019-04-04 10:11:02 +0800] [109420] [DEBUG] POST /report_start_game
'report_start_game(), current_app: 139984677481136'
[2019-04-04 10:11:02 +0800] [109420] [DEBUG] Closing connection. 

麻烦把相关命令行和调试信息上传来看看,记得用代码块。

插入代码块的方式:除了将所有代码缩进四格,更方便的插入代码块方式是使用三个连续的反引号作为开始和结束标记,比如:

```
def hello():
    return ‘Hello World’
```

会被渲染为:

 def hello():
     return 'Hello World'

具体参考论坛说明

已修正.感谢指点, 这样确实方便浏览.

你的socketio连接好像没有保持连接,总是不断重连?

如果是这样,感觉就是,如果后端开了3个进程,socketio重连后端会负载均衡,于是就分给不同的进程,然后就不好处理了。如果是单个进程那么重连都还是那个服务进程,问题不大。

多进程+多协程再加socketio通信,这知识点有点超纲了啊。

客户端没有不断重连, 连接是保持的.
:weary:这知识点是有些超了,目前我并不需要支持大并发,还是用一个进程先用着吧.
现在不影响开发进度, 只是我没有找到使用多进程的资料,不知道该该如何处理这个问题.
所以前来提问.

先挂着,说不准哪天就解决了:smirk::smirk::smirk:

:joy::joy::joy:希望这一天早点到来.

Flask-SocketIO 文档里有提到,Gunicorn 目前运行 Flask-SocketIO 程序时只能使用 1 个 worker:

Due to the limited load balancing algorithm used by gunicorn, it is not possible to use more than one worker process when using this web server. For that reason, all the examples above include the -w 1 option.

具体解决方法见文档 Using Multiple Workers 一节。

2 个赞

我想起來了!!!!我好像看过!!!

感谢指点, 当时确实没有看到这个说明(英语比较渣,学习中).

1 个赞

你好,向您请教个问题, 下面是我的启动文件main.py

app = Flask(__name__)
socketio = SocketIO(app)
socketio.run(app, host='0.0.0.0', debug=True)

现在有个视图函数文件引用了socketio

from mian import socketio

然后正常启动主函数不会有问题, 但是一旦用gunicorn 启动就会报错, 如下
ImportError: cannot import name ‘socketio’
请问是什么原因,希望能帮我解决一下, 谢谢

我最近在学Web开发,也想过这个问题,有关Gunicorn多进程部署的问题

1、CatChat程序使用全局变量统计在线人数的个数。

 但据我所知,Gunicorn的不同worker之间不会共享变量,所以这里可否改用Redis?

2、CatChat在不同worker中运行的时候,会导致消息不能在不同worker之间传播,我认为可以使用Redis的消息队列。

此外,还有两个有关数据库的问题:
3、在连接数据库时,Gunicorn的不同worker之间是共用一个连接还是分别创建不同的连接?
如果两个worker同时使用一个sqlite文件(.db)会不会有安全性问题?

4、我对于flask-sqlalchemy仍然不太了解,比如我有一个转账系统,需不需要额外加锁?我看《Flask Web实战》里的代码从不加锁,或者Flask-Sqlalchemy会自动加锁?