Nginx代理WebSocket
Nginx代理WebSocket
引言
聊天、实时推送、在线协作这类场景用WebSocket长连接。前端经过Nginx访问后端WS服务时,如果只按普通HTTP反代配置,握手会失败,因为WebSocket要先发起Upgrade协议升级,Nginx必须把升级头透传给后端。
WebSocket握手原理
客户端先发HTTP请求,带Upgrade: websocket和Connection: Upgrade头,后端同意后把HTTP协议升级成持久双向长连接。Nginx默认不透传这两个头,导致握手400。
标准代理配置
location /ws/ {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 3600s;
}
- proxy_http_version 1.1:WS基于HTTP/1.1;
- Upgrade $http_upgrade:透传客户端升级协议;
- Connection "upgrade":标记连接升级;
- read_timeout拉长:长连接默认60秒无数据会被Nginx断开。
用map统一处理
不同location可能同时有HTTP和WS,写map避免硬编码:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
# location内
proxy_set_header Connection $connection_upgrade;
普通HTTP请求$http_upgrade为空时走close,WS请求走upgrade,一套配置兼容。
常见问题
- 握手400/502:没加Upgrade和Connection头;
- 连接几十秒自动断开:read_timeout太短,按需拉长或服务端发心跳;
- wss(HTTPS)走Nginx终止TLS后,后端用ws即可;
- 后端端口和proxy_pass写对,别漏http://。
注意事项
- 长连接超时靠心跳和read_timeout共同维持;
- 集群WS要配合粘性会话或后端共享状态,否则消息发不到正确连接;
- HTTPS页面必须用wss://,浏览器会拦截混合内容;
- 改配置nginx -t后reload。
总结
Nginx代理WebSocket核心是加proxy_http_version 1.1、透传Upgrade和Connection头、拉长read_timeout,用map兼容普通HTTP。握手失败先查这三个头,断线先查超时和心跳。
Nginx配置websocket反向代理
前言
做实时聊天、推送、在线游戏,需要用 WebSocket。Nginx 当反向代理的时候,默认不支持 WebSocket 协议,需要额外配置。本文讲一下怎么配。
WebSocket 是什么
WebSocket 是一种全双工通信协议,浏览器和服务器建立连接后,可以一直保持连接,互相实时推送消息。
为什么需要特殊配置
普通 HTTP 请求是短连接,请求完就断了。WebSocket 是长连接,而且用的是 Upgrade 协议头。Nginx 默认的反向代理不支持这种升级,需要加特殊配置。
基础配置
location /ws/ {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
关键就是这三行:
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
完整配置示例
server {
listen 80;
server_name www.example.com;
root /var/www/html;
index index.html;
# WebSocket 代理
location /ws/ {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 300s;
}
# 普通 HTTP 代理
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
超时配置
WebSocket 是长连接,默认超时时间短了会自动断开。
proxy_read_timeout 300s;
proxy_send_timeout 300s;
意思是:5分钟没有数据传输才断开。
常见坑
坑1:WebSocket 连接失败
前端连 WebSocket 一直失败。
原因: Nginx 没配 Upgrade 和 Connection 头。
解决: 加上那三行关键配置。
坑2:连接几秒就自动断了
连上了,过一会儿就断了。
原因: Nginx 默认超时时间太短(60秒)。
解决: 调大 proxy_read_timeout。
坑3:HTTPS 下 WebSocket 连不上
HTTP 下正常,HTTPS 下连不上。
原因: 前端用了 ws://,但网站是 https 的,浏览器不让。
解决: 前端用 wss://(加密的 WebSocket)。
坑4:连接数太多被拒
很多人同时在线,新的连接被拒了。
原因: Nginx 或后端服务器连接数限制。
解决: 调大 Nginx 和后端的连接数限制。
总结
WebSocket 代理就三行核心配置:
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
记住: WebSocket 是长连接,记得调大超时时间,别让它自动断了。
遇到问题加QQ23979811 协助处理