HAProxy转发带请求头的POST请求返回503服务不可用故障排查
故障根因
从HAProxy日志的SC--终止标记、0/0/-1/-1/0耗时字段可以直接判定:故障出在TCP连接阶段,HAProxy根本没和后端服务器成功建立TCP连接,请求完全没转发到后端服务,和你提到的URL匹配、请求头校验逻辑没有任何关系。如果是请求头缺失、URL不匹配的问题,请求会正常到达后端,返回401/404状态码,日志里会记录后端返回的对应响应码,不会出现连接阶段的-1失败标记。
导致TCP连接失败的原因按出现概率排序:
- 最常见的是SELinux拦截:RHEL/CentOS/Rocky等默认开启SELinux的发行版上,默认SELinux策略禁止HAProxy进程对外发起网络连接,尤其是32401这类非系统默认服务的高位端口,会被内核直接拦截,表现为连接被拒绝,HAProxy日志就会打出SC错误、返回503。
- HAProxy主机到后端的网络连通性异常:你测试直连后端是从客户端机器(日志显示客户端IP为100.82.183.41)发起的,不是从HAProxy所在主机(100.82.182.73)发起的。HAProxy主机可能配置了iptables规则、安全组拦截出向流量,或者路由不通,导致自身无法访问100.82.185.122:32401端口。
- 配置存在冗余问题(不会直接触发本次503,但会引发后续请求异常):
- frontend段重复添加
X-Forwarded-Proto头:同时配置了旧版语法reqadd X-Forwarded-Proto:\ http和新版语法http-request add-header X-Forwarded-Proto http,会导致转发给后端的请求出现两个同名头,部分后端框架解析时会报错。 - 重复配置
option forwardfor:defaults段已经开启了该参数,frontend段重复配置没有实际作用。 - 未配置后端健康检查:当前backend的server行没有加
check参数,HAProxy不会主动探测后端存活状态,只要单次连接失败就直接返回503,不会做重试剔除、故障转移。
- frontend段重复添加
排查与修复步骤
- 先在HAProxy所在主机上直接测试后端连通性,执行命令:
如果命令直接报连接被拒绝、超时,先排查主机路由、iptables规则、云上安全组策略,确保HAProxy主机能正常访问后端的IP和端口。curl -v http://100.82.185.122:32401/services/collector/event - 如果HAProxy主机上curl能正常连通后端,直接检查SELinux状态:
如果返回结果为getenforceEnforcing,执行命令放开HAProxy的网络连接权限:
执行完后重新发测试请求,绝大多数同类场景到这一步就能恢复。setsebool -P haproxy_connect_any 1 - 修正冗余配置,优化后的配置参考如下:
这里新增了健康检查逻辑:因为访问后端接口不带认证头时会返回401,所以把健康检查的预期状态设为401,只要能返回401就证明后端服务存活,避免把正常服务判定为异常。同时删掉了重复的reqadd规则,避免出现重复请求头的问题。frontend main 0.0.0.0:80 option httpclose option forwardfor http-request add-header X-Forwarded-Proto http default_backend app backend app balance roundrobin option httpchk GET /services/collector/event http-check expect status 401 server app1 100.82.185.122:32401 check inter 5s fall 3 rise 2
验证标准
修复后重新运行Python测试脚本,不会再返回HAProxy自带的503页面:请求头缺失时返回后端的401响应,URL路径错误时返回404响应,参数正确时返回Splunk的写入成功响应。
内容的提问来源于stack exchange,提问作者Khayam Gondal
相关产品推荐
相关产品推荐

