怎么使用 HAProxy 实现简单的灰度发布流量权重调整?
核心结论:通过 HAProxy 的 ACL 规则和权重配置,可以实现按 10% 档位渐变的灰度发布,配合 socat 工具可实现不中断服务的热更新(基于 haproxy-2.4.22-3.el9_3.x86_64 版本验证)。
原因分析
HAProxy 采用事件驱动、单一进程模型,可支持数以万计的并发连接,但多核系统上扩展性较差,因此需要通过优化使每个 CPU 时间片做更多工作。灰度发布的核心难点在于:如何保证用户一旦进入新版本后不会再跳回老版本,以及如何控制流量和后端指定应用数量之间的比率。传统重启配置方式会造成业务突然中断,因此需要热更新方案。
解决方案
1. 基础配置搭建
在 global 模块中配置最大连接数和统计 socket:
global
maxconn 4000
stats socket /var/lib/haproxy/stats mode 600 level admin在 defaults 模块设置超时参数:timeout http-request 10s、timeout queue 1m、timeout connect 10s、timeout client 1m、timeout server 1m。
2. 基于 Cookie 的灰度分流
将流量分成 10 等分(cookie 按照 0-9 随机分发),按 10% 一档来渐变。配置示例:
acl cookie_gray_new hdr_reg(cookie) -i ha_gray_cookie=(1|2|3|4|5)(.*?) acl cookie_gray_old hdr_reg(cookie) -i ha_gray_cookie=(6|7|8|9|0)(.*?) use_backend app_1 if cookie_gray_new use_backend app_2 if cookie_gray_old
如后端 10 台机器,如果 30% 的灰度,前端将 30% 的流量切到后端机器总数的 30% 上面,即 cookie 为 0-2 的跳转到后端为新版本的三台机器上。
3. 基于 Header 的灰度控制
在请求 header 中增加 userid 参数,设定当 userid 小于 100 时访问灰度版本:
acl is_gray hdr(userid) -m int lt 100 use_backend hellogray if is_gray default_backend helloworld
此方式可在接入层实现灰度,无需在应用层进行控制,减少代码入侵。
4. 使用 socat 实现权重热更新
安装 socat:dnf install socat -y
查看当前权重:echo "get weight webcluster-http/webserver1" | socat stdio /var/lib/haproxy/stats
返回示例:1 (initial 1),表示当前权重为 1,初始权重也为 1。
修改权重命令:echo "set weight webcluster-http/webserver1 5" | socat stdio /var/lib/haproxy/stats
注意事项
1. HAProxy 反向代理的调度算法优先级低于 cookie,当连接已保持会话时调度算法无效,只有新连接请求或长连接失效时才使用调度算法。
2. 基于 cookie 的会话保持必须在 http 模式下,不支持 tcp 模式,会增加 HAProxy 负载且目前使用较少。
3. 如果后端会话时间比较长(如 mysql),建议使用 leastconn 算法;如果后端是静态 web,建议使用 roundrobin 算法。
4. HAProxy 是单进程软件,不建议开启多进程/多实例,nbproc 配置需谨慎。
5. 实现"一灰永灰"需要确保访问灰度版本的客户一直访问灰度版本,当请求 header 中没有灰度参数时会跳回原始版本,需在应用层配合处理。
参考来源
来源:CSDN - 基于 haproxy 实现灰度发布(2018 年 6 月 3 日)
来源:博客园 - 使用 socat 工具实现对 haproxy 权重配置的热更新(2026 年 2 月 3 日)
来源:知乎 - 一篇文章教会你如何使用 Haproxy(2024 年 8 月 12 日)
来源:51CTO - HAProxy 配置示例和需要考虑的问题(2026 年 4 月 13 日)