在 Uwsgi 和 Nginx 上使用 SocketIO 烧瓶
Posted
技术标签:
【中文标题】在 Uwsgi 和 Nginx 上使用 SocketIO 烧瓶【英文标题】:Flask with SocketIO on Uwsgi and Nginx 【发布时间】:2017-11-16 05:05:13 【问题描述】:我正在开发使用 WebSockets 与前端通信的 Flask 应用程序。它托管在 nginx 后面的 Amazon EC2 上,由 uwsgi 提供服务。
这是我用来服务应用程序的 uwsgi 配置:
[uwsgi]
plugins=python3,logfile
chdir=/srv/myapp/
master=true
home=/srv/myapp/.venv
module=application
callable=flask_app
uid=uwsgi
gid=myapp
socket=/srv/myapp/uwsgi.sock
chown-socket=uwsgi:myapp
chmod-socket=660
logto = /srv/myapp/logs/uwsgi.log
for-readline = /srv/myapp/.vars
env = %(_)
endfor =
并摘自涵盖 socketio 端点的 nginx 配置:
location /socket.io/
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass http://unix:///srv/myapp/uwsgi.sock;
没有 websockets 一切正常。在本地(我使用的是 Windows),一切都运行良好 - 我刚刚在客户端添加了 transport: ['websockets', 'polling']
以确保选择正确的协议。
在本地,我按照Flask-SocketIO 文档中的建议运行它,并且我安装了eventlet
(我不知道为什么,但在Windows x64 中gevent
包装器与Werkzeug
开发服务器配合不佳)。
部署应用时,我在浏览器中只看到错误websocket.js:112 WebSocket connection to 'ws://myapp.com/socket.io/?EIO=3&transport=websocket' failed: Error during WebSocket handshake: Unexpected response code: 502
。在服务器端,我在 uwsgi 日志中有以下内容:invalid request block size: 21573 (max 4096)...skip
。缓冲区大小的增加没有任何改变。
在 nginx 日志中我有:*413 upstream prematurely closed connection while reading response header from upstream, client: 171.6.248.10, server: localhost,, request: "GET /socket.io/?EIO=3&transport=websocket HTTP/1.1", upstream: "http://unix:///srv/myapp/uwsgi.sock:/socket.io/?EIO=3&transport=websocket", host: "myapp.com"
我尝试将这些行添加到 uwsgi.ini:
gevent=1000
http-websockets=true
没有成功
它是什么以及如何解决?
【问题讨论】:
几个 cmets。 uwsgi中的gevent
和http-websockets
配置项是必须的。 WebSocket 与 uwsgi 一起工作的唯一方法是通过 gevent。另外,我不明白您对 Werkzeug 开发服务器与 gevent 的引用,因为 gevent 使用它自己的 WSGI 服务器,与 Werkzeug 完全无关。至于主要问题,能不能检查一下Flask-SocketIO选择的异步模式是不是gevent_uwsgi
?
@Miguel 不幸的是我的应用程序使用 Python3 而gevent
uwsgi 插件(至少对于 Red Hat)仍然只支持 Python2.7
好吧,没有 gevent 的 uwsgi 不是受支持的配置,您也许可以让长轮询工作,但 WebSocket 是不可能的。您是否尝试过使用pip
安装uwsgi 而不是使用您的操作系统打包的那个?
不,我没有。我刚回到我的 Ginucorn 配置。
【参考方案1】:
这不是我问题的实际答案,只是一些信息
我的应用程序使用 Python 3,RedHat 提供来自 EPEL 的 Python3.4。尽管如此,UWSGI 只能使用 gevent
与 WebSockets 一起工作。所以,正如@Miguel 提到的,只有一种方法 - 使用长轮询。
解决方案
最后,我将 appserver 更改为提供开箱即用的 WebSockets 的 Gunicorn。
【讨论】:
以上是关于在 Uwsgi 和 Nginx 上使用 SocketIO 烧瓶的主要内容,如果未能解决你的问题,请参考以下文章
在 Docker 上使用 Nginx、uWSGI 和 Postgres 配置 Django
在centos上使用nginx+uwsgi部署django项目
markdown 如何在Ubuntu 14.04+上使用uWSGI和Nginx为Flask应用程序提供服务