apache mod_proxy_hcheck默认仅依赖http状态码和连接通断,易误判异步接口健康状态;须通过proxyhcexpr结合响应体、头信息及耗时等多维信号自定义判断,并配置hctemplate启用body解析与decompress支持。

Apache 的 mod_proxy_hcheck 默认只看 HTTP 状态码和连接是否通,对异步接口(如返回 202 Accepted 后后台处理、或轮询 /task/{id}/status)容易误判——它发一次请求就等响应,不理解“任务已接收但未完成”这类语义。要真实探测异步接口健康状态,必须绕过默认逻辑,用自定义表达式结合响应体内容、头信息、耗时等多维信号判断。
明确健康定义再配置
异步接口的“健康”不等于“能响应”,而应是:
- 请求能被正常接收(HTTP 202 或 200)
- 响应中包含有效 task ID 或 status 字段
- 后端健康端点(如
/health或/actuator/health)本身稳定返回 - 不因线程池满、消息队列积压等导致请求被静默丢弃
只靠 hcmethod=GET hcuri=/async 返回 202 是不够的,Apache 会把它当健康;但若后端已卡死,后续轮询 /task/xxx/status 全部超时,这个 202 就是“假活”。
用 ProxyHCExpr 解析响应体做真判断
必须启用 ProxyHCExpr,且不能只匹配状态码。例如后端返回 JSON:
{ "code": 0, "msg": "success", "task_id": "abc123" }
在 Apache 配置中写:
ProxyHCExpr async_ok {%{REQUEST_STATUS} == 202 && hc('body') =~ /"code"\s*:\s*0/ && hc('body') =~ /"task_id"\s*:\s*"/}
ProxyHCExpr async_down {%{REQUEST_STATUS} >= 400 || hc('body') !~ /"code"\s*:\s*[0-9]/}
关键点:
-
hc('body')可读取响应体(需hctemplate配合,见下) - 表达式支持正则、逻辑运算,可组合多个条件
- 若响应体含敏感字段(如 token),建议后端健康接口返回精简版(如仅
{"status":"ok","queue_len":12})
配置 hctemplate 显式声明要提取的内容mod_proxy_hcheck 默认不抓响应体,需先定义模板:
安全更新和维护 CLI Proxy API(CPA)部署与配置。用于 CPA 镜像升级、配置变更、认证目录兼容修复、上线验证与回滚。适用于用户提到“CPA 更新/升级/配置改了/容器重建/回滚”等场景。
ProxyHCTemplate async_check body=on headers=on
然后在 BalancerMember 中引用:
BalancerMember http://10.0.1.20:8080 \ hcmethod=GET hcuri=/health \ hctemplate=async_check \ hcexpr=async_ok \ hcinterval=15 hcfails=2 hcpasses=3
说明:
-
body=on是关键,否则hc('body')总为空 -
headers=on可用于检查X-RateLimit-Remaining或Retry-After等头 -
hcinterval=15避免高频探测压垮异步任务队列 -
hcfails=2降低误判门槛(异步服务偶发延迟高)
补充:用 ping + 自定义 URI 分层探测
单一 /health 可能掩盖问题。推荐双路径策略:
- 主探测走轻量
/health?quick=1(只查 DB 连接、线程池) - 辅探测走
/async/probe(提交一个最小 task 并立即 GET status,验证全链路)# 主健康检查(快) BalancerMember http://... hcuri=/health?quick=1 hcinterval=10 hcexpr=quick_ok
辅助探针(慢,每分钟一次,用独立模板)
ProxyHCTemplate deep_probe body=on timeout=8 BalancerMember http://... hcuri=/async/probe hctemplate=deep_probe \ hcinterval=60 hcexpr=deep_ok hcmethod=GET
注意 `timeout=8` 要大于后端 probe 接口实际耗时,否则总超时,节点反复 DOWN。 **调试务必看日志,别信 balancer-manager** `balancer-manager` 页面只显示最终状态(OK/DOWN),看不出为什么失败。开启: ```apache LogLevel proxy_hcheck:trace8
然后查 error_log,搜索 hcheck,你会看到:
- 是否发出请求、目标 URI、耗时
- 收到的状态码、响应头、截断的响应体
-
hcexpr计算过程(如evaluating hc('body') =~ /"code":0/ → false)
常见失败原因:后端 gzip 压缩响应体,Apache 默认不解压,hc('body') 拿到的是二进制乱码——此时加 hctemplate 参数 decompress=on 即可。










