HAProxy提前终止外部检查进程引发健康检查失败与进程堆积问题求助
看起来你遇到了HAProxy外部健康检查的几个棘手问题:脚本被提前终止、健康检查失败、进程堆积,还有对HAProxy多进程架构的疑惑,我来帮你一步步拆解分析:
一、为什么你的健康检查脚本会被提前杀死?
这是最核心的问题——你忽略了HAProxy外部检查的专属超时配置!
虽然你在defaults里设置了timeout check 10m,但这个参数只针对HAProxy内置的健康检查(比如TCP、HTTP检查)。对于外部检查,HAProxy有单独的external-check timeout参数,默认值只有5秒!
你的脚本里执行te-ping -c 50,假设每次探测间隔1秒,光是这一步就要50秒,远超过默认的5秒超时阈值。所以HAProxy会在5秒后强制杀死超时的te-ping进程,导致后续的awk因为管道断裂(上游进程被杀死,没有输出),抛出code 141 (Broken pipe)错误,最终整个脚本提前终止,健康检查失败。
二、为什么HAProxy会有两个主进程?
这是HAProxy正常的master-worker运行模式,是你配置里-W参数带来的效果:
- PID为1的是master进程:负责管理配置文件、处理信号(比如重启、重载),不处理实际流量和健康检查
- PID为8的是worker进程:负责实际处理客户端流量、执行健康检查等业务逻辑
这种架构是HAProxy推荐的生产环境运行模式,稳定性更高,不属于异常情况,不用纠结这个。
三、为什么会堆积多个检查进程?
主要有两个原因:
- 每次健康检查超时被HAProxy杀死后,脚本的子进程(比如bash、awk)可能没有被正确回收,残留下来
- 健康检查失败后,HAProxy会按照
fall 5的配置尝试多次重试,每次重试都会新启动一批检查进程,旧的残留进程没被清理,就会堆积起来
解决方案
1. 给外部检查设置足够的超时时间
在你的backend data_us配置里添加external-check timeout,值要大于你的脚本实际执行时间(比如给1分钟足够完成50次探测):
backend data_us option log-health-checks option external-check external-check command /etc/haproxy/healthcheck external-check timeout 1m # 关键添加这一行,覆盖默认5秒超时 server data_us proxy1-ap-southeast-1.aws.ca.thousandeyes.com:443 check inter 10m rise 5 fall 5 resolvers mynameservers resolve-prefer ipv4
2. 优化健康检查脚本,避免进程残留
在脚本开头添加信号捕获逻辑,确保脚本退出时能清理所有子进程:
#!/bin/bash set -x # 捕获退出信号,清理所有子进程 trap 'kill $(jobs -p)' EXIT not_used_1=$1 not_used_2=$2 host=$3 port=$4 packet_loss=$(/usr/local/bin/te-ping $host -p $port -c 50 | /usr/bin/awk '/packet loss/ { print strtonum($6) }') if [ "${packet_loss}" -lt 5 ]; then echo "${packet_loss}" exit 0; else exit 1; fi
另外,如果50次探测耗时太长,也可以考虑减少探测次数(比如-c 10),缩短脚本执行时间,降低超时风险。
3. 清理现有堆积的进程
先手动清理一次残留的检查进程,之后调整配置后就不会再堆积了:
pkill -f "/etc/haproxy/healthcheck" pkill -f "te-ping"
备注:内容来源于stack exchange,提问作者sgt

