跳转到内容
Guides 3 分钟阅读 1287 次浏览

WebSocket 连接的代理配置

配置与排查 WebSocket 代理连接的完整指南。掌握 GProxy,实现稳定可靠的实时通信。

WebSocket 连接的代理配置

代理 WebSocket 连接,意味着配置一台中间服务器正确处理 HTTP Upgrade 握手,并维持 WebSocket 通信所需的持久、全双工 TCP 连接。这种配置可为实时应用提供负载均衡、SSL 终止、缓存和访问控制等能力。

理解 WebSocket 代理

WebSocket 在单条 TCP 连接上,于客户端与服务器之间建立持久连接。这与通常采用短生命周期请求/响应循环的传统 HTTP 不同。从 HTTP 切换到 WebSocket,是通过 HTTP/1.1 协议中的"Upgrade"机制发起的。

客户端会发送一个带有特定头部的初始 HTTP GET 请求:
* Upgrade: websocket
* Connection: Upgrade
* Sec-WebSocket-Key: [base64 编码的 nonce]
* Sec-WebSocket-Version: 13

如果服务器支持 WebSocket,会返回 HTTP 101 Switching Protocols 状态,确认升级:
* HTTP/1.1 101 Switching Protocols
* Upgrade: websocket
* Connection: Upgrade
* Sec-WebSocket-Accept: [由客户端密钥派生出的响应密钥]

握手完成后,该连接不再是 HTTP,而是一条裸 TCP 套接字,WebSocket 帧在其上交换。代理服务器必须配置为正确转发这些 UpgradeConnection 头部,并随后维持这条长连接,既不缓冲也不提前关闭。

常见代理服务器的配置

Nginx

Nginx 通过处理 HTTP Upgrade 握手,可以有效代理 WebSocket 连接。关键在于把客户端的 UpgradeConnection 头部传给后端服务器,并确保使用 HTTP/1.1。

http {
    upstream websocket_backend {
        server backend_server_1:8080;
        server backend_server_2:8080;
    }

    server {
        listen 80;
        server_name yourdomain.com;

        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; # 如果后端依赖 host 头,这一项很重要
            proxy_read_timeout 86400s; # 针对长连接按需调整
            proxy_send_timeout 86400s;
            proxy_buffering off; # 关闭缓冲以传输实时数据
        }

        # 其他 HTTP location
        location / {
            proxy_pass http://other_http_backend;
            # ... 其他 HTTP 代理设置
        }
    }
}
  • proxy_http_version 1.1;Upgrade 头部机制必需。
  • proxy_set_header Upgrade $http_upgrade;:转发客户端的 Upgrade 头部。
  • proxy_set_header Connection "upgrade";:转发客户端的 Connection 头部。若未显式设为 "upgrade",Nginx 会在 HTTP/1.1 连接中自动把 Connection: upgrade 转换为 Connection: keep-alive。显式设置可确保 WebSocket 行为正确。
  • proxy_read_timeout / proxy_send_timeout:把默认值调高,防止 Nginx 因空闲而关闭长连接的 WebSocket。
  • proxy_buffering off;:阻止 Nginx 缓冲响应,这对实时 WebSocket 通信保持最小延迟至关重要。

Apache HTTP Server

Apache 可通过 mod_proxy 的组成部分 mod_proxy_wstunnel 代理 WebSocket 连接。请确保已启用 mod_proxymod_proxy_httpmod_proxy_wstunnel

<VirtualHost *:80>
    ServerName yourdomain.com

    # 启用代理模块
    LoadModule proxy_module modules/mod_proxy.so
    LoadModule proxy_http_module modules/mod_proxy_http.so
    LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so

    # 代理 WebSocket 连接
    <Location /ws/>
        ProxyPass ws://backend_server:8080/ws/
        ProxyPassReverse ws://backend_server:8080/ws/
    </Location>

    # 代理安全 WebSocket 连接(WSS)
    <Location /wss/>
        ProxyPass wss://backend_server:8443/wss/
        ProxyPassReverse wss://backend_server:8443/wss/
    </Location>

    # 其他 HTTP location
    <Location />
        ProxyPass http://other_http_backend/
        ProxyPassReverse http://other_http_backend/
    </Location>
</VirtualHost>
  • ProxyPass ws://...ws:// 方案告诉 mod_proxy_wstunnel 处理 WebSocket 升级。安全 WebSocket 请使用 wss://
  • ProxyPassReverse:确保响应头中的 URL 被正确重写。
  • 当指定 ws://wss:// 时,Apache 的 mod_proxy 会自动处理 UpgradeConnection 头部。

HAProxy

HAProxy 自 1.5 版起支持 WebSocket 代理。它可以运行在 http 模式下检查头部,或在 tcp 模式下做裸转发。对 WebSocket 而言,常见做法是使用 http 模式并配以检测升级请求的专门规则。

global
    log /dev/log    local0 info
    maxconn 4000
    user haproxy
    group haproxy
    daemon

defaults
    mode http
    log global
    option httplog
    option dontlognull
    timeout connect 5000ms
    timeout client 50000ms # 为客户端侧 WebSocket 连接调高
    timeout server 50000ms # 为后端侧 WebSocket 连接调高

frontend http_frontend
    bind *:80
    acl is_websocket hdr(Upgrade) -i websocket
    use_backend ws_backend if is_websocket
    default_backend http_backend

backend ws_backend
    mode http
    # 该选项对 HTTP 模式下的 WebSocket 至关重要;它让 HAProxy 在 HTTP
    # 升级完成后切换为 TCP 隧道。
    option http-tunnel
    server backend_ws_1 backend_server_1:8080 check
    server backend_ws_2 backend_server_2:8080 check

backend http_backend
    mode http
    server backend_http_1 backend_server_3:80 check
  • acl is_websocket hdr(Upgrade) -i websocket:定义一个 Access Control List(ACL),匹配包含 Upgrade: websocket 头部的请求(不区分大小写)。
  • use_backend ws_backend if is_websocket:把 WebSocket 升级请求导向 ws_backend
  • option http-tunnel:这是关键。当 HAProxy 检测到 Upgrade 头且启用该选项时,会在初始 HTTP 握手之后从 HTTP 解析模式切换为裸 TCP 隧道,从而让 WebSocket 协议畅通运行。
  • timeout client / timeout server:对 WebSocket 后端应大幅调高这些超时,避免 HAProxy 关闭长连接。

常见问题排查

连接掉线或超时

  • 代理超时:最常见的原因。请确保 proxy_read_timeoutproxy_send_timeout(Nginx)、timeout clienttimeout server(HAProxy)或其他代理中的等效设置对 WebSocket 连接足够大(例如 24 小时以上)。
  • 空闲连接:部分代理或网络设备会激进地关闭空闲 TCP 连接。若 WebSocket 协议带有保活机制(如 ping/pong 帧),请在客户端和服务器两侧都配置为定期发送 ping。
  • 负载均衡器空闲超时:若代理前方还有负载均衡器,它也可能有自己的空闲超时。请检查这些设置。

HTTP 400 Bad Request(Upgrade 头缺失或不正确)

  • 客户端请求:确认客户端正确发送了 Upgrade: websocketConnection: Upgrade 头部。
  • 代理配置:确保代理已配置为把这些头部转发给后端。
    • Nginx:检查 proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade";
    • Apache:确保已启用 mod_proxy_wstunnel,且 ProxyPass 使用 ws://wss://
    • HAProxy:确认 acl is_websocket 正确识别了 Upgrade 头,且 use_backend 将其导向设置了 option http-tunnel 的后端。

HTTP 502 Bad Gateway

  • 后端服务器问题:代理从后端收到了无效响应。
    • 后端 WebSocket 服务器是否在运行并监听预期端口?
    • 后端是否已正确配置以处理 WebSocket 升级?
    • 查看后端服务器日志中的错误。
  • 网络连通性:确认代理能通过指定端口访问后端服务器。
  • 代理缓冲:虽然 proxy_buffering off 通常有利于 WebSocket,但数据量过大或配置有误时,代理若难以处理数据流,有时也会导致 502。

安全注意事项(SSL/TLS 终止)

  • WSS(安全 WebSocket):对于安全 WebSocket 连接(wss://),必须由代理完成 SSL/TLS 终止。
    • 代理监听 443 端口(或其他安全端口),完成 TLS 握手,然后把解密后的 WebSocket 流量转发给后端(内部通常走普通的 ws://http://)。
    • WSS 的 Nginx 示例:
      ```nginx
      server {
      listen 443 ssl;
      server_name yourdomain.com;
      ssl_certificate /etc/nginx/ssl/yourdomain.crt;
      ssl_certificate_key /etc/nginx/ssl/yourdomain.key;
      location /ws/ {
          proxy_pass http://websocket_backend; # 后端可以是普通 HTTP
          proxy_http_version 1.1;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection "upgrade";
          proxy_set_header Host $host;
          proxy_read_timeout 86400s;
          proxy_send_timeout 86400s;
          proxy_buffering off;
      }
      

      }
      `` * **Origin 头:**WebSocket 客户端会发送Origin` 头。后端服务器出于安全考虑常常校验该头部。若后端依赖它,请确保代理没有剥离或修改该头部。

代理缓冲区限制

  • Nginx:proxy_buffering off; 至关重要。若不设置,Nginx 可能缓冲较大的 WebSocket 消息,带来延迟或引发超时。
  • HAProxy:option http-tunnel 通过切换到裸 TCP 解决此问题。

面向 WebSocket 的代理服务器对比

特性 Nginx Apache HTTP Server (mod_proxy_wstunnel) HAProxy
配置方式 手动转发头部 专用 ws:// / wss:// 指令 ACL 与 option http-tunnel
复杂度 中等 中等 中到高(涉及高级功能时)
性能 高(事件驱动) 中等(基于进程/线程) 高(事件驱动)
SSL/TLS 终止 出色 良好 出色
负载均衡 轮询、IP hash、least_conn 轮询 丰富(多种算法、健康检查)
会话保持 IP hash(基础)、第三方模块 有限 基于 cookie、源 IP
缓冲控制 proxy_buffering off mod_proxy_wstunnel 处理 option http-tunnel 关闭 HTTP 缓冲

关键注意事项

  • 会话保持:某些 WebSocket 应用中,客户端需要在整个会话期间连到同一台后端服务器(例如服务端保存了状态)。
    • Nginx:upstream 块中使用 ip_hash
    • HAProxy:使用 balance sourcecookie 指令。
    • 条件允许时,请把后端应用设计为无需会话保持即可横向扩展,这会简化负载均衡。
  • 健康检查:在代理中为后端 WebSocket 服务器配置可靠的健康检查,确保只有健康的服务器接收 WebSocket 升级请求。
  • 日志:在代理和后端配置完善的日志。WebSocket 连接问题可能是瞬时的,详细日志对诊断必不可少。
  • HTTP/2 与 WebSocket:尽管 WebSocket 的升级握手通常使用 HTTP/1.1,但它可以与 HTTP/2 共存。不过 WebSocket 协议本身并不直接跑在 HTTP/2 帧之上。处理来自客户端的 HTTP/2 的代理,在向后端发起 WebSocket 升级时通常会降级为 HTTP/1.1。
已更新: 04.03.2026
返回分类

试用我们的代理

遍布 100+ 国家的 20,000+ 代理

support_agent
GProxy Support
Usually replies within minutes
Hi there!
Send us a message and we'll reply as soon as possible.