配置 Nginx 代理 WebSocket 流量 发表于 2025-12-12 | 分类于 nginx | 暂无评论 ### 一、Websocket简介 Websocket是一种在单个TCP连接上进行全双工通信的协议。它使得客户端和服务器之间的数据交换变得更加简单,允许服务器主动向客户端推送数据,而不像HTTP协议那样只能由客户端发起请求。例如,在一个实时聊天应用中,使用Websocket,服务器可以在有新消息时直接将消息推送给客户端,而不必等待客户端询问是否有新消息。 WebSocket 协议推出比较早,当时只能利用 HTTP/1.1 协议的 Upgrade 来升级。但后来有了 HTTP/2 和 HTTP/3,讲道理 WebSocket 也应该支持使用新的 HTTP 协议来传输才对。但是,HTTP/2 和 HTTP/3 不支持 Upgrade 机制,所以相关设计一直到 2018 年的 RFC84411 和 2022 年的 RFC92202 才稳定下来。但是现在业界已经开始在推 WebTransport 协议了,它底层基于 QUIC 协议,除了跟 WebSocket 一样支持双向通信外,还支持类似 UDP 协议的不可靠数据传输,比WebSocket 更强大。 WebSocket 本质上就是 TCP 连接,只不过它在创建 TCP 连接时需要先发起一次 HTTP 请求,之后就跟 HTTP 协议没有关系了。 这里的关键是一旦完成升级,TCP 连接就会一直保持,而且代理需求为每个 WebSocket 连接维持一个跟上游的 TCP 连接。这样原来针对 HTTP 协议设计的上游连接策略就不适用了。为此 Nginx 对 Upstream 模块做了魔改,当它发现 HTTP 请求中有 Upgrade 和 Connection 的时候就会进入 TCP 转发模式。 ### 二、Nginx在Websocket中的角色 反向代理:Nginx最常见的角色是作为反向代理服务器。在Websocket场景下,它位于客户端和真正的Websocket服务器之间。客户端以为自己是直接与Websocket服务器通信,但实际上所有请求和响应都经过Nginx。例如,当浏览器中的JavaScript代码发起一个Websocket连接请求,这个请求首先到达Nginx。 负载均衡:如果有多个Websocket服务器来处理大量连接,Nginx可以将传入的Websocket请求均匀地分配到这些后端服务器上,以提高系统的整体性能和可用性。 ### 三、Nginx实现Websocket原理 (一)协议升级 HTTP升级请求:Websocket连接的建立是从一个HTTP请求开始的。客户端发送一个带有特殊头部的HTTP请求,其中包含`Upgrade: websocket`和`Connection: Upgrade`头部字段。这个请求告诉服务器,客户端希望将协议从HTTP升级到Websocket。 Nginx处理升级请求:Nginx接收到这个请求后,会检查请求头部是否符合Websocket协议升级的要求。如果符合,Nginx会将请求转发给后端的Websocket服务器,并且在转发过程中也会保留`Upgrade`和`Connection`头部,使得后端服务器知道这是一个协议升级请求。 (二)保持连接 长连接机制:一旦协议升级成功,Websocket连接就建立起来了。这个连接是一个长连接,它不会像普通的HTTP连接那样在一次请求 响应后就关闭。Nginx会维护这个连接,确保客户端和后端Websocket服务器之间的数据能够持续、稳定地传输。 心跳机制(可选):为了检测连接是否仍然有效,有时候会采用心跳机制。无论是客户端还是服务器(在Nginx的协助下)可以定期发送一个小的数据包(心跳包)来确认连接的活性。如果一段时间没有收到心跳包,就可以认为连接已经断开。 (三)数据转发 双向数据传输:在Websocket连接建立后,数据可以在客户端和服务器之间双向传输。当客户端发送数据给服务器时,Nginx会将数据原封不动地转发给后端Websocket服务器;同样,当后端服务器发送数据给客户端时,Nginx也会将数据转发给客户端。例如,在一个实时股票价格更新的应用中,后端服务器不断推送最新的股票价格数据,Nginx就负责把这些数据转发给所有连接的客户端。 ### 四、nginx配置 HTTP 协议规定 Upgrade/Connection 只能点对点传递,不能跨节点传递,也就是说,处理 HTTP 请求的中间节点不能将下游发过来的 Upgrade/Connection 头信息转发给上游。所以我们在配置 Nginx 转发 WebSocket 协议需要额外指定。 ```shell server { listen 8080; location /chat { proxy_pass http://127.0.0.8888; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } } ``` 注意,这里的 HTTP 版本只能是 1.1 还要额外指定 Upgrade 和 Connection 两个头信息。 因为 Nginx 要为每个客户端连接维持一个同上游的 TCP 连接,每个上游连接需要占用一个本地 TCP 端口号。如果是单网卡,一台机器最多 65535 个端口号。所以单机最多代理也就六万多个 WebSocket 连接。这跟传统的 HTTP 代理有天差地别。 如果业务并发连接数很多,就需要设置 Nginx 集群。 ```shell +---+ Client -------\ /------> Nginx ------>|App| +---+ x +---+ Client ------->|NLB|-------> Nginx ------>|App| +---+ x +---+ Client -------/ \------> Nginx ------>|App| +---+ ``` 这里每个 Nginx 使用相同的配置,支持转发请求到所有的 Upstream 服务。ASCII 画图比较费事,我用两个 x 表示每个 Nginx 都能跟所有 App 服务通信。在客户端与 Nginx 之间放一个 Network Load Balancer (NLB)。注意,这个 NLB 需要支持一致性哈希转发,相同 IP 地址和端口号的请求需要一直转发给同一个 Nginx,避免 TCP 连接被断开。而且一致性啥希在添加 Nginx 节点时不会影响已建建立的 WebSocket 连接,从而实现高可用和动态扩容。 网络型负载均衡(NLB)是一种四层(传输层)负载均衡服务,专注于处理TCP、UDP等协议流量,通过智能分配网络请求实现高可用性和性能扩展 配置好之后不要忘记压测,可以使用 thor4 工具来压测 WebSocket 代理。 参考: >https://blog.csdn.net/chinansa/article/details/143829239 https://tao.zz.ac/nginx/websocket.html