Pub/Sub超时应设Redis还是Nginx?是否需使用心跳机制?
Flask+Redis SSE:超时配置与心跳机制的正确做法
一、超时设置的正确位置与必要性
绝对不能完全禁用Nginx的超时设置,否则会导致大量闲置长连接占用资源,引发连接泄漏问题。正确的配置需要覆盖Nginx和WSGI服务器(如Gunicorn/uWSGI)两层:
1. Nginx侧配置
- 开启HTTP/1.1支持:SSE依赖长连接,HTTP/1.1默认支持
keep-alive,需显式设置proxy_http_version 1.1,并清空Connection头避免Nginx主动断开。 - 关闭代理缓冲:SSE是流式传输,缓冲会导致消息延迟,必须设置
proxy_buffering off。 - 设置合理的
proxy_read_timeout:建议设为300秒(5分钟),这个时间要比心跳间隔长,确保心跳能在超时前触发,避免连接被断开。
示例Nginx配置:
location /sse { proxy_pass http://your_flask_upstream; # 替换为你的Flask服务地址 proxy_http_version 1.1; proxy_set_header Connection ""; proxy_buffering off; proxy_read_timeout 300s; }
2. WSGI服务器侧配置
生产环境用Gunicorn或uWSGI部署Flask时,要设置比Nginx超时更长的服务端超时,避免WSGI服务器先于Nginx断开连接。比如Gunicorn可以加参数:
gunicorn --timeout 310 app:app
这里设310秒,比Nginx的300秒多10秒,留足缓冲时间。
二、心跳机制是必选项
即使设置了合理的超时,中间网络设备(如路由器、防火墙)也可能因为长时间无数据传输主动断开连接。心跳机制的作用就是定期发送无意义的帧,维持连接活性。
按照SSE规范,发送注释帧(以:开头,后跟换行)是最优方案,客户端会自动忽略这类帧,不会干扰业务逻辑。
Flask中结合Redis实现心跳的示例代码:
from flask import Response, stream_with_context import redis import time def sse_stream(): redis_client = redis.Redis(host='localhost', port=6379) pubsub = redis_client.pubsub() pubsub.subscribe('sse_topic') # 替换为你的Redis订阅主题 heartbeat_interval = 30 # 每30秒发一次心跳 last_heartbeat_time = time.time() while True: # 检查是否需要发送心跳 if time.time() - last_heartbeat_time > heartbeat_interval: yield ':\n\n' last_heartbeat_time = time.time() # 监听Redis消息,设置超时避免阻塞 msg = pubsub.get_message(timeout=10) if msg and msg['type'] == 'message': # 格式化SSE消息格式 yield f'data: {msg["data"].decode("utf-8")}\n\n' @app.route('/sse') def sse_endpoint(): return Response( stream_with_context(sse_stream()), mimetype='text/event-stream' )
三、总结
- 必须保留超时设置,分别在Nginx和WSGI服务器配置,且WSGI超时要略长于Nginx。
- 心跳机制是刚需,用SSE注释帧定期发送,既能维持连接,又不影响业务。
- Nginx的流式传输配置(HTTP/1.1、关闭缓冲)是SSE正常工作的基础。
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

