nginx轮询与sse可共存,但需为sse路径单独关闭缓冲、禁用缓存、延长超时、透传长连接,并配置合理的upstream健康检查参数以避免误剔节点。

Nginx 轮询本身不干扰 SSE,但默认缓冲和超时机制会直接破坏流式语义。要让轮询正常工作的同时透传 SSE,必须在 upstream 负载均衡逻辑之上,针对 SSE 路径单独关闭缓冲、延长超时、禁用缓存,并确保 HTTP/1.1 长连接透传。
轮询与 SSE 共存的关键前提
轮询负责把请求均匀分发到后端节点,而 SSE 要求每个连接持续、低延迟、逐条推送。两者不冲突,但需满足:
- 后端微服务是无状态的(SSE 连接本身可重建,不依赖服务端 session)
- 所有后端节点均支持
text/event-stream响应且返回标准头(Cache-Control: no-cache,Connection: keep-alive) - Nginx 不对 SSE 请求做连接复用或健康检查干扰(如
max_fails不应误判长空闲为失败)
SSE 路径专属配置(必须写在具体 location 块内)
只对 /api/events、/sse 等实际提供流式接口的路径生效,避免影响其他 API:
location /api/events {
proxy_pass http://ms_backend; # 指向已定义的轮询 upstream 组
# 关键:禁用缓冲与缓存,保障实时透传
proxy_buffering off;
proxy_cache off;
# 延长超时,适应 SSE 长连接(通常空闲数分钟)
proxy_read_timeout 86400;
proxy_send_timeout 86400;
# 强制 HTTP/1.1 + 清除 Connection 头,防中间代理断连
proxy_http_version 1.1;
proxy_set_header Connection "";
# 透传客户端真实信息(不影响流式,但建议保留)
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
# 显式声明分块传输,避免 Nginx 尝试计算 Content-Length
chunked_transfer_encoding on;
# 告知浏览器“无服务端缓冲”,增强前端兼容性
add_header X-Accel-Buffering no;
}
upstream 轮询组需配合的健壮性设置
虽然轮询本身无需额外参数,但为避免 SSE 连接被误摘除,建议微调健康检查粒度:
upstream ms_backend {
server 192.168.1.10:8080 max_fails=1 fail_timeout=60s;
server 192.168.1.11:8080 max_fails=1 fail_timeout=60s;
server 192.168.1.12:8080 max_fails=1 fail_timeout=60s;
# 可选:启用连接池复用,减少握手开销(适合高并发 SSE)
keepalive 32;
}
-
max_fails=1是关键:SSE 连接空闲期长,fail_timeout设为 60s 以上,避免因短暂无响应就剔除节点 -
keepalive 32配合proxy_http_version 1.1和proxy_set_header Connection "",让 Nginx 与后端保持长连接池,提升吞吐
验证是否生效的实操方法
- 连续发起 6 次
curl -Ns http://your-domain/api/events,观察响应头中的X-Upstream-Addr是否按轮询顺序循环(如192.168.1.10:8080,192.168.1.11:8080, …) - 用浏览器打开 EventSource,检查 Network 面板中该请求状态是否长期 pending,且 data 事件随时间逐条到达(非整块返回)
- 查看 Nginx access log,确认
upstream_response_time字段显示为0.001, 0.002, ...等毫秒级值,而非几十秒整块延迟
不复杂但容易忽略











