You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask SSE接口部署后不稳定,遇504网关超时问题求助

SSE 部署不稳定问题的解决方案

你的 Flask SSE 端点代码如下:

@app.route('/chatlisten', methods=['GET'])
def listen():
    from_id, to_id = int(request.args['from_id']), int(request.args['to_id'])
        
    def stream():
        message = message_queue.listen(from_id, to_id)
        while True:
            msg = message.get()
            yield f"data:{msg}\n\n"

    return Response(stream(), mimetype='text/event-stream')

一、让 SSE 可靠运行的关键优化

1. 定期发送心跳包

网络层(Nginx、负载均衡)会主动断开长时间无数据的连接,必须每隔一段时间发心跳维持连接:

# 若使用标准库 Queue,导入对应异常类
from queue import Empty

def stream():
    message = message_queue.listen(from_id, to_id)
    while True:
        try:
            # 30秒超时,没新消息就发心跳
            msg = message.get(timeout=30)
            yield f"data:{msg}\n\n"
        except Empty:
            # 空注释帧作为心跳,客户端不会解析该内容
            yield ":heartbeat\n\n"

2. 配置正确的响应头

禁止缓存、强制长连接、关闭中间件缓冲:

response = Response(stream(), mimetype='text/event-stream')
response.headers['Cache-Control'] = 'no-cache'
response.headers['Connection'] = 'keep-alive'
response.headers['X-Accel-Buffering'] = 'no'  # 告诉Nginx不要缓冲流式响应
return response

3. 确保 Gevent 猴子补丁生效

用 gevent worker 必须打补丁,否则阻塞操作会卡死 worker。在应用入口最顶部添加:

from gevent import monkey
monkey.patch_all()

启动 gunicorn 时指定 worker 类并设置长超时:

gunicorn -k gevent -w 4 --timeout 3600 your_app:app

4. 处理客户端断开连接

捕获断开异常,及时清理资源,防止 worker 进程挂起:

from flask import request

def stream():
    message = message_queue.listen(from_id, to_id)
    try:
        while True:
            try:
                msg = message.get(timeout=30)
                yield f"data:{msg}\n\n"
            except Empty:
                yield ":heartbeat\n\n"
            # 检查客户端是否主动断开连接
            if request.environ.get('werkzeug.request').is_disconnected:
                break
    except GeneratorExit:
        # 客户端断开后,取消队列监听
        message_queue.unlisten(from_id, to_id)

二、关于端口与 504 超时的疑问

  • SSE 不需要额外端口:它是基于 HTTP/HTTPS 的长连接协议,和你的 Flask 应用共用同一个端口,无需单独开放端口。
  • 504 超时的核心原因:
    • 中间件超时:Nginx、CDN 这类中间件默认有连接超时(比如 60 秒),如果 SSE 长时间没数据(没消息也没心跳),会被主动断开并返回 504。
    • Gunicorn 超时设置过短:如果 gunicorn 的 --timeout 参数设得太小,会把长时间运行的 SSE 连接对应的 worker 进程杀死,导致连接中断。
    • Nginx 缓冲未关闭:Nginx 默认会缓冲响应,等整个响应完成再发给客户端,但 SSE 是流式输出,缓冲会导致数据延迟甚至连接断开,必须关闭。

附:Nginx 反向代理配置(若使用 Nginx)

location /chatlisten {
    proxy_pass http://你的Flask应用地址;
    proxy_buffering off;  # 必须关闭缓冲
    proxy_read_timeout 3600;  # 超时设长一点,比如1小时
    proxy_set_header Connection '';
    proxy_http_version 1.1;
    chunked_transfer_encoding off;
}

内容的提问来源于stack exchange,提问作者Gunslinger

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 12:26:11