nginx实现websocket转发的关键是在location块中配置协议升级头和长连接参数。需设置proxy_http_version 1.1、proxy_set_header upgrade $http_upgrade、proxy_set_header connection "upgrade",并调整proxy_read_timeout等超时值及禁用缓冲。

在 Nginx 中实现 WebSocket 协议的升级转发,关键不是靠 location 的匹配规则本身,而是通过在匹配到的 location 块中正确设置 HTTP 头部和连接行为,让 Nginx 主动完成从 HTTP 到 WebSocket 的协议升级(Upgrade)和连接保持(Connection: upgrade)。WebSocket 本质是基于 HTTP 的 Upgrade 机制建立长连接,Nginx 默认会关闭后端非 HTTP/1.1 连接或丢弃 Upgrade 请求头,因此必须显式配置。
确保 location 能匹配 WebSocket 请求路径
WebSocket 客户端发起的请求通常是标准 HTTP GET,带特定请求头(Upgrade: websocket、Connection: Upgrade),URL 路径可能为 /ws、/api/ws 或带查询参数(如 /ws?token=abc)。location 应覆盖这些请求:
- 用前缀匹配即可:
location /ws { ... }可匹配/ws、/ws/、/ws/chat - 如需精确匹配路径(不含子路径),用等号:
location = /ws { ... } - 若路径含动态参数或版本前缀,可用正则:
location ~ ^/api/v\d+/ws { ... } - 注意:Nginx 匹配 location 时,不关心请求方法(GET/POST)或是否含 Upgrade 头,只看 URI;所以只要路径对上,后续配置才起作用
必须添加的 WebSocket 升级代理头
Nginx 默认不会透传 Upgrade 和 Connection 头给后端,也不会将当前连接升级为长连接。需在 location 块中显式设置:
-
proxy_http_version 1.1;:强制使用 HTTP/1.1(WebSocket Upgrade 依赖此版本) -
proxy_set_header Upgrade $http_upgrade;:将客户端的 Upgrade 头(通常是 "websocket")原样传给后端 -
proxy_set_header Connection "upgrade";:固定写死为 "upgrade",通知 Nginx 自身要升级连接;注意不能写$http_connection,因为客户端可能发Connection: keep-alive, Upgrade,Nginx 需要明确指令 - 其他可选但推荐:
proxy_set_header Host $host;、proxy_set_header X-Real-IP $remote_addr;等用于后端日志或鉴权
调整超时与缓冲以适配长连接
WebSocket 是长生命周期连接,Nginx 默认的短超时(如 60 秒)会导致连接被意外关闭:
-
proxy_read_timeout 86400;:设置 Nginx 读取后端响应的超时(即心跳间隔上限),建议设为大值(如 24 小时),实际由业务心跳控制 -
proxy_send_timeout 86400;:同理,控制发送超时 -
proxy_buffering off;:禁用缓冲,避免 Nginx 缓存 WebSocket 帧导致延迟或粘包(WebSocket 数据是二进制帧流,非传统 HTTP body) -
tcp_nodelay on;:启用 Nagle 算法禁用,减少小包延迟(对实时性要求高的场景有效)
完整示例配置
假设后端 WebSocket 服务运行在 127.0.0.1:8080,前端通过 wss://example.com/ws 访问:
upstream websocket_backend {
server 127.0.0.1:8080;
}
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location /ws {
proxy_pass http://websocket_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 86400;
proxy_send_timeout 86400;
proxy_buffering off;
tcp_nodelay on;
}
}
重启 Nginx 后,客户端调用 new WebSocket("wss://example.com/ws") 即可完成握手并维持长连接。











