HAProxy 如何实现 WebSocket 长连接反向代理配置

文章导读
HAProxy 从 1.5 版本起原生支持 WebSocket,配置关键在于正确传递 Upgrade 请求头并设置独立的隧道超时时间,无需额外模块。
📋 目录
  1. 完整配置示例(Frontend + Backend)
  2. 配置核心原理
  3. 实操步骤
  4. 验证方法
  5. 常见坑
  6. 参考来源
A A

HAProxy 从 1.5 版本起原生支持 WebSocket,配置关键在于正确传递 Upgrade 请求头并设置独立的隧道超时时间,无需额外模块。

先说结论:配置核心是放行升级头、显式配置路由策略和调整超时策略,确保长连接不被误杀。

  • 适合 HTTP/1.1 协议下的 WebSocket 业务场景
  • 必须在 frontend 中显式指定 default_backend 或使用 ACL 路由
  • backend 中必须配置 timeout tunnel 以维持长连接
  • 验收需借助 WebSocket 客户端工具或浏览器控制台

完整配置示例(Frontend + Backend)

以下是一段最小可用的 frontend 与 backend 联动配置片段,重点在于路由规则和超时设置:

frontend http_front
    bind *:80
    mode http
    # 基于路径匹配 WebSocket 请求
    acl is_ws path_beg /ws
    # 匹配到 WebSocket 路径则转发到 ws_backend
    use_backend ws_backend if is_ws
    # 默认后端(非 WebSocket 请求)
    default_backend web_backend

backend ws_backend
    balance roundrobin
    mode http
    # 关键:设置隧道超时,防止长连接被切断
    timeout tunnel 1h
    server ws1 192.168.1.10:8080 check
    server ws2 192.168.1.11:8080 check

backend web_backend
    balance roundrobin
    mode http
    server web1 192.168.1.20:8080 check

配置核心原理

WebSocket 连接建立初期是一个标准的 HTTP 请求,包含Upgrade: websocketConnection: Upgrade头。HAProxy 检测到这两个头后,会将连接模式从“请求 - 响应”切换为“隧道”模式,此后数据双向透传,不再解析 HTTP 协议。

注意:HAProxy 不会根据 Upgrade 头自动选择 backend,必须在 frontend 中显式配置default_backend或使用use_backend规则。Upgrade 头仅影响连接模式切换,不负责路由选择。

默认情况下,HAProxy 的timeout server控制后端空闲超时,但一旦进入隧道模式,timeout tunnel才会生效。如果未配置timeout tunnel,HAProxy 可能沿用较短的 HTTP 超时设置,导致长连接在空闲时被切断。

实操步骤

1. 确认版本

在终端执行haproxy -v,确保版本不低于 1.5。生产环境建议使用 2.0 及以上 LTS 版本,以获得更好的稳定性和兼容性。

2. 修改配置文件

编辑/etc/haproxy/haproxy.cfg,参考上述完整配置示例。重点检查:

  • frontend 段是否配置了default_backenduse_backend路由规则,确保请求能到达 backend。
  • backend 段是否设置了timeout tunnel,根据业务需求设置隧道空闲超时。

注意:不要在全局默认值中随意调大所有超时,建议仅在 WebSocket 业务的 backend 中单独设置。

3. 检查配置并重载

执行haproxy -c -f /etc/haproxy/haproxy.cfg检查语法。确认无误后,执行systemctl reload haproxy或发送SIGUSR2信号平滑重载,避免中断现有连接。

HAProxy 如何实现 WebSocket 长连接反向代理配置

验证方法

1. 使用 wscat 工具

如果有wscat工具,执行wscat -c ws://your-haproxy-ip/ws,保持连接空闲超过普通 HTTP 超时时间(如 30 秒),观察是否断开。

2. 浏览器开发者工具

在 Chrome 浏览器中打开 Network 面板,筛选 WS 请求。查看握手响应状态码是否为 101 Switching Protocols,并观察连接是否能在页面空闲时保持 Established 状态。

3. 查看 HAProxy 日志

开启 HAProxy 日志后,观察日志中是否有异常的超时关闭记录。WebSocket 连接建立后,日志通常会记录一次完整的握手过程,后续数据透传不会每条都记录。

常见坑

1. 路由配置缺失

仅配置 backend 而忘记在 frontend 指定default_backend,导致请求无法到达后端。必须显式配置路由规则。

2. 超时参数混淆

很多配置只改了timeout server,忽略了timeout tunnel。记住:握手阶段看 server/client 超时,建立连接后看 tunnel 超时。

3. 头部被清洗

检查是否有其他中间件或 HAProxy 自身的http-request规则误删了ConnectionUpgrade头,这会导致升级失败退回普通 HTTP 响应。

参考来源

  • HAProxy 官方文档 - Configuration Manual
  • URL: https://docs.haproxy.org/