WebSocket 是一种网络通信协议,它在单个 TCP 连接上提供全双工(双向)通信信道。与 HTTP 不同,WebSocket 允许服务器主动向客户端推送数据,而不需要客户端先发送请求。这使得 WebSocket 非常适用于需要实时数据交换的应用,如在线游戏、聊天应用、实时体育更新等。
WebSocket 连接通过 HTTP 协议开始,通过一种称为"升级"的机制,将 HTTP 连接升级为 WebSocket 连接。客户端发送一个包含 Upgrade: websocket 和 Connection: Upgrade 头部的 HTTP 请求,服务器如果支持 WebSocket,则会响应一个 101 状态码(切换协议)来确认升级。
与传统 HTTP 的区别:
| 特性 | HTTP | WebSocket |
|---|---|---|
| 通信方式 | 请求-响应(半双工) | 双向实时通信(全双工) |
| 连接生命周期 | 短连接(每次请求新建) | 长连接(保持连接) |
| 数据推送 | 只能客户端主动请求 | 服务器可主动推送数据 |
| 头部开销 | 每次请求都有完整头部 | 建立连接后头部开销小 |
| 延迟 | 较高(每次建立连接) | 极低(保持连接) |
WebSocket 工作原理:
- 握手阶段:客户端通过 HTTP Upgrade 请求建立连接
- 协议升级:服务器返回 101 Switching Protocols
- 数据交换:双方通过建立的连接自由发送数据
完成配置文件
bash
# 连接升级映射(推荐)
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
location /websocket {
# 基本代理配置
proxy_pass http://websocket_backend;
proxy_http_version 1.1;
# WebSocket 升级头
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
# 客户端信息传递
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_read_timeout 3600s; # 读取超时(长连接)
proxy_send_timeout 3600s; # 发送超时
proxy_connect_timeout 30s; # 连接超时
# 缓冲区设置
proxy_buffering off; # 禁用缓冲(实时性要求高时)
# 其他优化
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
}
关键参数解释:
map $http_upgrade $connection_upgrade:- 用于根据客户端请求中的
Upgrade头来设置Connection头。如果客户端请求升级协议,则设置Connection为upgrade,否则为close。
- 用于根据客户端请求中的
proxy_http_version 1.1:- WebSocket代理必须使用HTTP/1.1,因为WebSocket握手基于HTTP/1.1的Upgrade机制。
proxy_set_header Upgrade $http_upgrade:- 将客户端的
Upgrade头原样传递给后端服务器。
- 将客户端的
proxy_set_header Connection $connection_upgrade:- 根据
map指令的结果设置Connection头,值为upgrade或close。
- 根据
- 其他代理头 :
Host、X-Real-IP、X-Forwarded-For、X-Forwarded-Proto等用于传递客户端信息给后端服务器。
- 超时设置 :
proxy_read_timeout:设置从后端服务器读取响应的超时时间,对于WebSocket长连接,需要设置得较长(如3600秒)。proxy_send_timeout:设置向后端服务器发送请求的超时时间。proxy_connect_timeout:设置与后端服务器建立连接的超时时间。
SSL 终止配置:
bash
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location /websocket {
proxy_pass http://backend_ws; # 后端使用普通 WS
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
# 传递 SSL 信息
proxy_set_header X-Forwarded-Proto https;
}
}
什么场景下使用?
- 实时应用:如聊天应用、实时游戏、股票行情推送、体育直播更新等。
- 协作工具:如在线文档编辑、远程桌面、白板等。
- 物联网(IoT):设备通过WebSocket与服务器保持长连接,实时上报数据和接收指令。
- 监控系统:实时监控服务器状态、应用性能等。
在需要实时双向通信的应用场景中,使用 Nginx 代理 WebSocket 是生产环境的最佳实践。