Nginx 代理 SSE (Server‑Sent‑Events / Event‑Stream) 完整配置

14次阅读
没有评论

Content‑Type: text/event-stream,长连接、单向推送,Nginx 默认配置很容易断连、超时。

一、核心问题

SSE 是长连接 HTTP 流,Nginx 默认超时很短,会主动断开;同时默认开启缓冲,会把 event‑stream 缓存住不实时下发到浏览器。

必须关闭缓存、调大超时、禁用代理缓冲

二、最简可用配置片段

location /sse {
    proxy_pass http://127.0.0.1:8080;

    # 关键 SSE 参数
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "keep-alive";

    # 关闭Nginx响应缓冲,数据立刻发给客户端
    proxy_buffering off;
    proxy_cache off;

    # 长连接超时,设置很大,SSE依靠客户端心跳断开
    proxy_read_timeout 86400s;
    proxy_send_timeout 86400s;

    # 可选:关闭gzip,部分浏览器代理压缩会卡住流
    proxy_set_header Accept-Encoding "";
}

参数逐条解释

  1. proxy_http_version 1.1 Nginx 默认向后端用 HTTP/1.0,Connection: close,长连接直接废掉,SSE 必断。必须切 1.1。
  2. proxy_set_header Connection "keep-alive" 维持后端长连接。

WebSocket 需要 Upgrade,纯 SSE 不需要 Upgrade;写上也无害。

  1. proxy_buffering off; 最关键!Nginx 默认缓存后端返回流,攒够一块再发给浏览器,text/event-stream 消息延迟、收不到。
  2. proxy_read_timeout 86400s Nginx 默认 proxy_read_timeout 60s:后端 60 秒没发任何数据 → Nginx 主动关闭连接。 SSE 如果长时间没有推送消息就会被断开。后端最好定时发 : ping\n\n 心跳包保活。

三、后端心跳保活(推荐)

服务端定时发送注释心跳,防止 Nginx 超时切断:

: ping

以冒号开头为 SSE 注释,浏览器忽略,仅用来占住连接。

四、HTTPS + SSE 完整站点示例

server {
    listen 443 ssl;
    server_name sse.example.com;

    ssl_certificate cert/fullchain.pem;
    ssl_certificate_key cert/privkey.pem;

    location /stream {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Host $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_set_header Connection "keep-alive";
        proxy_buffering off;
        proxy_cache off;
        proxy_read_timeout 86400s;
        proxy_send_timeout 86400s;
        proxy_set_header Accept-Encoding "";
    }
}

五、常见坑 & 排错清单

  1. 每隔 60 秒断开连接 👉 原因:proxy_read_timeout 默认 60s,改大 + 后端发心跳。
  2. 收不到消息,浏览器一直 pending 👉 大概率忘记 proxy_buffering off
  3. 连接很快断掉,根本连不上 👉 没加 proxy_http_version 1.1
  4. Nginx gzip 卡住流 👉 proxy_set_header Accept-Encoding ""; 让后端不返回压缩内容。

六、Nginx 开源版 vs Nginx‑Plus

开源版 Nginx 原生支持 SSE 代理,不需要任何额外模块。

七、前端 JS 测试代码

const evtSource = new EventSource("https://sse.example.com/stream");
evtSource.onmessage = (e)=>{
    console.log("收到",e.data);
};
evtSource.onerror = err=>{
    console.error("连接错误",err);
};
正文完
可以使用微信扫码关注公众号(ID:xzluomor)
post-qrcode
 0
评论(没有评论)
验证码