Flask SSE与Nginx配合运行异常问题求助
我之前在Flask+Gunicorn+Nginx的栈上跑SSE时踩过一模一样的坑!核心问题就是Nginx默认的缓冲、超时和连接配置会破坏SSE的长连接实时特性,结合你的场景给你一套完整的解决方案:
一、补全并修复Nginx配置
你的现有配置已经加了keepalive和proxy_buffering off,但还缺几个关键项,完整的配置应该是这样:
upstream backend { server 127.0.0.1:5000; keepalive 100; # 维持与后端Gunicorn的长连接池,这个配置是对的 } server { listen 80; access_log /var/log/nginx/client-access.log; error_log /var/log/nginx/client-error.log; location / { include proxy_params; proxy_pass http://backend; # 彻底关闭缓冲和缓存,避免SSE事件被积压 proxy_buffering off; proxy_cache off; # 必须用HTTP/1.1才能支持长连接,HTTP/1.0不兼容 proxy_http_version 1.1; # 强制设置连接为keep-alive,防止Nginx或后端主动断开 proxy_set_header Connection "keep-alive"; # 调整超时时间,避免Nginx因长时间无数据传输断开连接 # 可以根据你的业务需求修改,比如设置为1小时 proxy_connect_timeout 3600s; proxy_send_timeout 3600s; proxy_read_timeout 3600s; # 禁用压缩,压缩会把SSE的多个事件打包成块,前端无法实时解析 proxy_set_header Accept-Encoding ""; } # 如果你的SSE有单独的路径(比如/sse),建议单独配置这个location更精准 location /sse { include proxy_params; proxy_pass http://backend; proxy_buffering off; proxy_cache off; proxy_http_version 1.1; proxy_set_header Connection "keep-alive"; proxy_connect_timeout 3600s; proxy_send_timeout 3600s; proxy_read_timeout 3600s; proxy_set_header Accept-Encoding ""; } }
每个配置的作用简单说下:
proxy_http_version 1.1:SSE依赖HTTP长连接,只有1.1版本支持proxy_set_header Connection "keep-alive":确保从前端→Nginx→Gunicorn整个链路都维持长连接proxy_buffering off:Nginx默认会把后端响应缓冲完再发给前端,这直接让SSE的实时性报废,必须关proxy_read_timeout:设置足够长的超时,不然Nginx会因为几分钟没数据就主动断开连接Accept-Encoding "":禁用压缩,压缩会打乱SSE的逐帧传输格式
二、Gunicorn必须用异步Worker
Gunicorn默认的同步Worker会被SSE的长连接占满,导致其他请求无法处理,一定要用异步Worker,比如gevent:
- 先安装gevent:
pip install gevent - 启动Gunicorn时指定Worker类型:
gunicorn --worker-class=gevent --workers=4 --bind=127.0.0.1:5000 your_flask_app:app
- 记得在你的Flask入口文件开头加上猴子补丁,不然gevent无法正确处理IO:
from gevent import monkey monkey.patch_all()
三、Flask-SSE的小检查
一般flask-sse会自动处理响应头,但可以手动确认你的SSE端点返回的头是否正确:
- Content-Type必须是
text/event-stream - Cache-Control设置为
no-cache - Connection设置为
keep-alive
如果是自定义SSE端点,代码可以这么写:
from flask import Response import time @app.route('/custom-sse') def custom_sse(): def event_generator(): while True: # 生成符合SSE格式的事件(注意结尾的两个换行) yield 'data: 新消息来了!\n\n' time.sleep(5) return Response( event_generator(), mimetype='text/event-stream', headers={ 'Cache-Control': 'no-cache', 'Connection': 'keep-alive' } )
最后记得重启Nginx和Gunicorn,然后用浏览器开发者工具的Network面板看SSE请求:状态码200,响应会持续保持打开状态,每有事件就会有数据块传输。
内容的提问来源于stack exchange,提问作者Vitor Villar
相关产品推荐
相关产品推荐

