在 Nginx 配置中,map $http_upgrade $connection_upgrade
主要用于 WebSocket 代理,以确保正确处理 Upgrade
头部,实现 WebSocket 连接。以下是完整的 Nginx 配置示例:
完整配置示例(WebSocket 代理)
http {
# 定义一个变量 $connection_upgrade
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name example.com;
location /ws/ {
proxy_pass http://backend_server;
proxy_http_version 1.1; # WebSocket 需要 HTTP/1.1
proxy_set_header Upgrade $http_upgrade; # 传递 Upgrade 头
proxy_set_header Connection $connection_upgrade; # 传递 Connection 头
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}
参数解析
map $http_upgrade $connection_upgrade
- 该指令将
Upgrade
头部映射到Connection
头部:
- 如果
$http_upgrade
变量有值(比如websocket
),$connection_upgrade
设为upgrade
。 - 如果
$http_upgrade
为空,则设为close
。
proxy_pass http://backend_server;
- 代理请求到后端 WebSocket 服务器。
proxy_http_version 1.1;
- WebSocket 需要 HTTP/1.1 支持,必须指定。
proxy_set_header Upgrade $http_upgrade;
- 传递
Upgrade
头部,以保持 WebSocket 连接。
proxy_set_header Connection $connection_upgrade;
- 传递
Connection
头部,确保 WebSocket 代理正确处理升级请求。
$http_upgrade
变量的值来自 HTTP 请求头中的 Upgrade
头部,它用于指示客户端希望升级的协议类型。常见的值包括:
1. WebSocket 连接
当浏览器或客户端请求 WebSocket 连接时,HTTP 请求头通常包含:
Upgrade: websocket
Connection: Upgrade
此时,在 Nginx 配置中,$http_upgrade
变量的值为:
websocket
在 Nginx 配置中:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
这里的 '' close;
并不是直接关闭连接的意思,而是设置 Connection
头的值为 "close"
,告诉客户端和服务器在当前请求处理完成后不要保持连接。
含义解析
- 当
$http_upgrade
为空(即请求没有Upgrade
头):
proxy_set_header Connection $connection_upgrade;
这相当于:
proxy_set_header Connection "close";
这意味着 Nginx 会在响应后关闭连接(不复用 HTTP 连接),但不会主动断开连接或拒绝请求。
- 当
$http_upgrade
有值(如websocket
):
proxy_set_header Connection "upgrade";
这允许 HTTP 连接升级到 WebSocket 等协议。
普通 HTTP 请求的情况
如果是普通的 HTTP 请求(如浏览器访问网页),通常不会包含 Upgrade
头部,因此:
-
$http_upgrade
为空(''
) -
$connection_upgrade
设为"close"
- 服务器会处理 HTTP 请求并正常返回响应
- 但 Nginx 会在响应后关闭连接,而不会保持 Keep-Alive 连接
是否会影响普通 HTTP 请求?
不会影响 HTTP 请求的正常处理,普通 HTTP 请求仍然会被 Nginx 正常响应。唯一的区别是:
-
Connection: close
→ 响应后关闭连接 -
Connection: keep-alive
→ 响应后保持连接(若启用keepalive
)
如果你希望在普通 HTTP 请求中也保持连接,可以修改 map
规则:
map $http_upgrade $connection_upgrade {
default upgrade;
'' keep-alive;
}
这样,普通 HTTP 请求的 Connection
头就会被设为 keep-alive
,从而避免每次请求都重新建立 TCP 连接,提高性能。
总结
-
Connection: close
不会直接关闭连接,而是响应后不复用连接。 -
map
语句不会影响请求的正常处理,只是修改Connection
头的行为。 - 可以改成
keep-alive
,让普通 HTTP 请求保持连接,提高性能。
WebSocket 本身就是一种长连接。它与传统的 HTTP 连接不同,允许服务器和客户端之间进行全双工通信,而不需要客户端频繁发送请求来保持连接。
1. WebSocket 为什么是长连接?
WebSocket 连接的生命周期如下:
- 客户端发起 WebSocket 握手
- 通过 HTTP/1.1 的
Upgrade
头进行协议升级:
GET /ws HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
- 服务器响应:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
- 连接升级后,通信协议从 HTTP 切换为 WebSocket。
- 保持连接
- 连接建立后,WebSocket 不会像普通 HTTP 请求一样在响应后立即关闭。
- 服务器和客户端可以相互发送消息,并且消息可以是双向的(全双工通信)。
- 连接会一直保持,直到客户端或服务器主动关闭。
- 连接关闭
- WebSocket 连接可以在任意一方调用
close()
方法后关闭:
- 客户端主动关闭 (
ws.close()
) - 服务器主动关闭
- 连接超时、网络异常等
2. WebSocket vs. HTTP 连接
HTTP(短连接) |
WebSocket(长连接) |
|
通信方式 |
请求-响应模式(客户端发请求,服务器返回数据) |
双向通信(客户端和服务器都能主动发送消息) |
连接状态 |
一次请求完成后通常关闭连接 |
连接保持直到显式关闭 |
延迟 |
需要每次建立 TCP 连接 |
一次握手后持续使用,低延迟 |
适用场景 |
普通网页访问、API 请求 |
实时聊天、gupiao行情、在线游戏等 |
3. WebSocket 是否需要 Connection: keep-alive
?
不需要!
- HTTP 的
keep-alive
主要用于 复用 TCP 连接,减少每次请求的握手开销。 - WebSocket 连接建立后,本身就是 持久连接,不需要
keep-alive
。 - WebSocket 协议升级后,HTTP 头部(如
keep-alive
)不再适用。
4. WebSocket 代理中的 map
规则
在 Nginx 配置 WebSocket 代理时,通常使用:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
这里:
- WebSocket 连接的
Upgrade: websocket
头部会使Connection: upgrade
,保持 WebSocket 连接。 - 普通 HTTP 请求没有
Upgrade
头,因此Connection: close
,表示请求完成后关闭连接(短连接)。 - WebSocket 不依赖
keep-alive
,它是天然的长连接。
5. 什么时候 WebSocket 可能会断开?
尽管 WebSocket 是长连接,但以下情况可能导致断开:
- 服务器或客户端主动关闭
- 服务器调用
ws.close()
- 客户端调用
websocket.close()
- 网络异常
- 断网、超时、IP 变更等
- 代理/防火墙干预
- 一些代理服务器或防火墙可能会在一段时间内关闭空闲 WebSocket 连接。
- 解决方案:
-
心跳机制:定期发送
ping
数据包 -
设置 Nginx
proxy_read_timeout
:
location /ws/ {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 3600s; # 避免超时
}
总结
✅ WebSocket 本质上是长连接,在连接建立后可以持续通信,直到主动关闭或发生网络问题。
✅ 不需要 keep-alive
,因为 WebSocket 连接本身就是持久的。
✅ 需要处理可能的网络断开、代理超时等情况,以确保连接稳定。
你是遇到 WebSocket 连接被断开的情况,还是想优化 WebSocket 代理?
nginx 这些配置参数是否会影响websocket的长连接?
keepalive_timeout 65 ;
proxy_connect_timeout 300;
proxy_send_timeout 300;
proxy_read_timeout 300;
是的,这些 Nginx 配置参数会影响 WebSocket 长连接的稳定性,具体影响如下:
1. keepalive_timeout 65;
- 作用:
- 适用于 HTTP 连接,控制客户端空闲连接在关闭前的最大等待时间(秒)。
- 如果客户端在
keepalive_timeout
时间内没有新请求,Nginx 关闭该连接。
- 对 WebSocket 的影响:
-
WebSocket 连接不受
keepalive_timeout
影响,因为 WebSocket 是升级后的持久连接,而keepalive_timeout
仅影响 HTTPkeep-alive
连接。 - 无影响,但如果你的 WebSocket 应用有 HTTP 轮询(long polling),该参数可能会影响 HTTP 连接的持久性。
✅ 结论:对 WebSocket 无影响,主要影响普通 HTTP 长连接。
2. proxy_connect_timeout 300;
- 作用:
- 控制 Nginx 连接到后端服务器的超时时间(单位:秒)。
- 如果在
proxy_connect_timeout
时间内无法建立 TCP 连接(比如后端服务器响应慢),Nginx 将返回错误。
- 对 WebSocket 的影响:
- 仅影响 WebSocket 连接的初始建立阶段(握手阶段)。
- 不会影响已建立的 WebSocket 连接。
- 适用于后端服务器延迟较高的情况(如 WebSocket 服务器启动较慢)。
✅ 结论:仅影响 WebSocket 连接建立,不影响已建立的长连接。
3. proxy_send_timeout 300;
- 作用:
- 控制 Nginx 向后端服务器发送数据的超时时间(单位:秒)。
- 如果 Nginx 在
proxy_send_timeout
时间内未能成功向后端发送完整的数据包,则连接会被关闭。
- 对 WebSocket 的影响:
- WebSocket 服务器通常需要持续发送数据,如果 300 秒内没有任何数据发送,Nginx 可能会关闭 WebSocket 连接。
- 适用于控制长时间无数据发送的 WebSocket 连接,但通常 WebSocket 服务器会发送心跳包避免超时。
⚠️ 建议修改:如果 WebSocket 连接需要长时间保持,增大 proxy_send_timeout
,比如:
proxy_send_timeout 3600s; # 1小时
✅ 结论:影响 WebSocket 长时间无数据发送的情况,建议增加超时时间或实现心跳机制。
4. proxy_read_timeout 300;
- 作用:
- 控制 Nginx 从后端服务器读取数据的超时时间(单位:秒)。
- 如果 Nginx 在
proxy_read_timeout
时间内未能收到来自后端的任何数据,Nginx 会关闭连接。
- 对 WebSocket 的影响:
- 如果 WebSocket 连接在 300 秒内没有收到任何消息,Nginx 可能会断开连接。
- 适用于 WebSocket 服务器的长时间无数据传输的情况。
- 解决方法:
- 增加超时时间,比如:
proxy_read_timeout 3600s; # 1小时
- 使用 WebSocket 心跳(ping/pong),让服务器定期发送 ping,确保连接保持活跃。
⚠️ 建议修改:如果 WebSocket 需要长期连接,建议增大 proxy_read_timeout
,避免意外断开。
✅ 结论:影响 WebSocket 长时间无数据接收的情况,建议增加超时时间或使用心跳包。
最佳 WebSocket 配置(优化长连接)
server {
listen 80;
server_name example.com;
location /ws/ {
proxy_pass http://backend_server;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_connect_timeout 10s; # 连接后端服务器超时
proxy_send_timeout 3600s; # 发送数据超时
proxy_read_timeout 3600s; # 读取数据超时
send_timeout 3600s; # 发送超时(客户端)
}
}
总结
参数 |
默认值 |
作用 |
对 WebSocket 的影响 |
优化建议 |
|
|
控制 HTTP |
无影响 |
无须更改 |
|
|
连接后端 WebSocket 服务器超时 |
仅影响连接建立 |
可调小,如 |
|
|
向后端发送数据超时 |
影响长时间无数据发送 |
增大,如 |
|
|
从后端读取数据超时 |
影响长时间无数据接收 |
增大,如 |
???? 重点优化:
-
proxy_read_timeout
和proxy_send_timeout
需要足够大,防止 WebSocket 连接因超时断开。 - WebSocket 服务器定期发送心跳包(ping/pong),保证连接存活。
-
keepalive_timeout
不影响 WebSocket,可忽略。