如果 Server-Sent Events (SSE) 在 Nginx 中无法生效,你可以按照以下步骤排查问题:
1. 确保 Nginx 正确代理 SSE 请求
Nginx 默认会尝试缓冲响应内容,而 SSE 是流式输出,不能被缓冲。你需要确保 proxy_buffering
关闭:
location /sse {proxy_pass http://backend_server;proxy_buffering off; # 关闭缓冲proxy_cache off; # 关闭缓存proxy_set_header Connection ''; # 确保 Nginx 不会断开 SSE 连接chunked_transfer_encoding on; # 确保传输支持 chunked encoding
}
检查点:
proxy_buffering off
确保数据实时传输。proxy_cache off
防止 Nginx 缓存 SSE 响应。Connection ''
避免 Nginx 关闭 SSE 连接。chunked_transfer_encoding on
允许流式数据传输。
2. 检查后端是否正确返回 SSE 响应
后端必须满足以下 SSE 规范:
Content-Type
设置为text/event-stream
- 以
data:
开头发送数据,并以\n\n
结尾 - 保持 HTTP 连接不关闭
你可以用 curl
测试后端 SSE 响应:
curl -v http://backend_server/sse
如果返回:
HTTP/1.1 200 OK
Content-Type: text/event-stream
Transfer-Encoding: chunked
并且输出类似:
data: Hello Worlddata: Another event
说明后端是正常的。
如果没有 Content-Type: text/event-stream
,那就要检查后端是否正确设置了这个头。
3. 确保 HTTP 连接不会被 Nginx 过早关闭
Nginx 可能因为超时关闭 SSE 连接,需要调整超时参数:
location /sse {proxy_pass http://backend_server;proxy_buffering off;proxy_cache off;proxy_set_header Connection '';# 防止超时断开proxy_read_timeout 3600s;proxy_send_timeout 3600s;keepalive_timeout 3600s;
}
检查点:
proxy_read_timeout
:防止 Nginx 关闭长连接。proxy_send_timeout
:确保 SSE 连接能长期保持。keepalive_timeout
:保持客户端连接,防止过早关闭。
4. 确保 Nginx 没有 gzip 压缩 SSE
SSE 不支持 gzip 压缩,如果 Nginx 试图压缩流式数据,可能会导致 SSE 失效。确保你 没有启用 gzip:
location /sse {proxy_pass http://backend_server;proxy_buffering off;gzip off;
}
检查点:
gzip off;
关闭压缩,SSE 不能被 gzip 处理。
5. 检查 WebSocket 代理是否干扰 SSE
如果你的应用同时使用 SSE 和 WebSocket,Nginx 可能会错误地将 SSE 请求当作 WebSocket 连接进行处理。你可以在 location /sse
中明确指定 不使用 WebSocket:
proxy_set_header Upgrade '';
proxy_set_header Connection '';
检查点:
proxy_set_header Upgrade '';
避免 Nginx 误将 SSE 当作 WebSocket 代理。
6. 检查浏览器 SSE 连接是否被阻止
有些浏览器可能因为 CORS 或代理问题阻止 SSE 连接,检查 Chrome 开发者工具 (F12) → Network → SSE 请求状态:
- 状态码 200:正常
- 状态码 403/404:检查 Nginx 配置或后端
- ERR_CONNECTION_CLOSED:可能是 Nginx 或后端关闭了连接
可以在 Nginx 端允许 CORS:
location /sse {add_header Access-Control-Allow-Origin *;add_header Cache-Control no-cache;
}
7. 检查防火墙 & 代理
如果 SSE 连接在 生产环境不可用,但本地测试正常:
- 检查防火墙是否关闭长连接
- 检查 CDN 或反向代理是否缓存或阻断 SSE
如果使用 Cloudflare 或某些代理,可能需要手动关闭 HTTP 缓存或开启 WebSocket 兼容模式。
8. 确保前端正确处理 SSE
前端代码示例:
const eventSource = new EventSource("/sse");eventSource.onmessage = function(event) {console.log("Received:", event.data);
};eventSource.onerror = function(err) {console.error("SSE error:", err);
};
如果 eventSource
立即 onerror
,通常是 Nginx 配置问题。
总结
✅ 最小化 Nginx SSE 代理配置:
location /sse {proxy_pass http://backend_server;proxy_buffering off;proxy_cache off;gzip off;proxy_set_header Connection '';proxy_read_timeout 3600s;proxy_send_timeout 3600s;
}
✅ 确保后端返回正确的 SSE 响应
Content-Type: text/event-stream
- 以
data:
开头,每条消息以\n\n
结尾 - HTTP 连接持续不关闭
✅ 使用 curl
检查后端
curl -v http://backend_server/sse
✅ 浏览器开发者工具 (F12) 查看 SSE 请求状态
- 200 OK:正常
- 403/404:权限或路由问题
- ERR_CONNECTION_CLOSED:可能是超时或 Nginx 关闭连接
如果仍然有问题,可以打开 Nginx 日志:
tail -f /var/log/nginx/access.log
tail -f /var/log/nginx/error.log
这样你就能定位 SSE 在 Nginx 中不能生效的原因 🚀