HAProxy多后端负载均衡异常,foo后端宕机时首次请求返回503错误
问题根因
- 当前配置的ACL规则在请求进入frontend阶段执行,依赖HAProxy异步更新的后端健康状态:当foo后端刚宕机时,健康检查还未完成标记foo1为down,此时
nbsrv(foo)返回值仍为1,请求会被转发到foo后端,连接foo1失败后直接返回503,直到健康检查完成更新状态,后续请求才会命中规则走bar后端。 - 默认的
option redispatch仅对GET、HEAD等幂等请求生效,非幂等请求连接失败时不会重分发,也会导致503。
解决方案
提供两种适配不同场景的配置方案:
方案1:配置backend级别的备用后端(推荐,兼容性最好)
不需要在frontend配置ACL判断,直接在foo后端声明bar为备用后端,foo可用时所有请求走foo,foo不可用时自动切到bar,请求连接失败时会自动重试到备用后端,避免首次请求503,配置更简洁:
defaults log global mode http timeout connect 5000ms timeout client 50000ms timeout server 50000ms timeout queue 50000ms timeout http-request 60000ms timeout http-keep-alive 5000ms max-keep-alive-queue 10 option httplog # 开启全量请求重分发,重试3次,业务允许非幂等请求重试时开启 option redispatch 3 retries 3 option forwardfor option http-server-close # 后端节点被标记为宕机时立即关闭所有关联会话,避免残留请求转发 default-server on-marked-down shutdown-sessions frontend front bind *:80 default_backend foo backend foo # 缩短健康检查间隔,1秒检查一次,连续3次失败标记为宕机 server foo1 10.0.0.1:80 check inter 1000 rise 2 fall 3 # 直接指定bar为备用后端,HAProxy 1.6及以上版本支持该参数 fallback bar backend bar server bar1 10.0.1.1:80 check server bar2 10.0.1.2:80 check
如果使用1.6以下版本不支持fallback指令,可以直接在foo后端把bar的节点标记为备用节点,效果一致:
backend foo server foo1 10.0.0.1:80 check inter 1000 rise 2 fall 3 server bar1 10.0.1.1:80 check backup server bar2 10.0.1.2:80 check backup
方案2:保留原ACL逻辑,修复状态滞后问题
如果需要保留原有的frontend判断逻辑,调整以下配置即可:
- 缩短foo后端的健康检查间隔,降低状态更新延迟:
backend foo server foo1 10.0.0.1:80 check inter 1000 rise 2 fall 3
- 在defaults段开启全量重分发,连接失败时自动重试其他可用后端:
option redispatch 3 retries 3 default-server on-marked-down shutdown-sessions
- 若使用HAProxy 2.0及以上版本,可新增503错误自动重试逻辑:
frontend front bind *:80 acl use_bar nbsrv(foo) -m int lt 1 use_backend bar if use_bar default_backend foo # 捕获503错误自动重试 http-request retry-on 503
内容的提问来源于stack exchange,提问作者JDev
相关产品推荐
相关产品推荐

