土法炼钢 · 系统与基础设施

【HAProxy 数据面】排障与可观测:五轴清单与 stats / sess / 日志落点

文章导航

分类入口
networkproxy
标签入口
#haproxy#troubleshooting#observability#show-sess#stats#acl#health-check#3.4.3

目录

「后端健康」与「客户端 503 / 卡死 / 偶发 RST」可以同时为真。排障若从 Grafana 面板名或业务口号起步,容易在 LB、TLS、上游之间空转。本系列前 12 篇给出的坐标系,足以把多数故障压进有限几格。

本文是排障篇:给出五轴清单,并说明 Runtime 只读命令、HTTP 日志与 stats 页面各自钉在哪一层。命令只写语义;不粘贴未实跑的 show info / show sess / CSV stats 输出。菜谱脚本见 network/56

本文是「HAProxy / 数据面代理内核」系列第 13 篇(共 14 篇)。→ 系列目录

篇目 核心内容
第 12 篇 · Seamless reload FD 交接与排空
第 13 篇 · 排障与可观测 五轴 → 信号落点
第 14 篇 · 选型收束 排除树与开放问题

版本锚定:HAProxy 3.4.3 Management Guide Unix Socket commands(show info / show stat / show sess / show errors / show activity 等)。清单是工程方法,不是厂商 runbook 全文。


一、先选轴,再动命令

Accept / bind 轴:   听没听上?FD 交接是否半成功?
Stream / mux 轴:    连接进了哪条 stream?卡在编解码/复用?
ACL / 路由轴:       规则命中了哪个 backend?改写副作用?
Upstream / health 轴:server 状态、队列、检查与熔断感?
Reload / Runtime 轴: 新旧进程并存?热改与文件真相分叉?
flowchart TD
  symptom["Symptom: 5xx / stall / RST / sticky miss"] --> axis["Pick one axis"]
  axis --> ab["Accept / bind"]
  axis --> sm["Stream / mux"]
  axis --> ar["ACL / routing"]
  axis --> uh["Upstream / health"]
  axis --> rr["Reload / Runtime"]
  ab --> sig["show info / listeners / logs"]
  sm --> sess["show sess / show errors"]
  ar --> acl["show acl / map + httplog"]
  uh --> st["show stat / show servers / table"]
  rr --> proc["Master CLI show proc"]

默认顺序(可裁剪):

  1. 日志定层(frontend / backend / 终止状态码)。
  2. show stat(或 stats 页面)看 frontend 与 server 计数器是否在动。
  3. 怀疑会话级问题 → show sess(短格式扫,再按 id 深挖)。
  4. 窗口内刚 reload → Master CLI show proc,对 current / leaving 分别核对。
  5. 仍不一致 → 回对应机制篇(04–12),不要先改业务代码。

Stats socket 与 Master CLI 同属高权限运维面:生产必须 UNIX 权限或网络隔离;level admin 可改流量,只读排障也应审计。

五轴不是五个独立产品,而是同一次请求在不同失败切面上的投影。一次「用户说慢」可能同时触及 mux 缓冲与 upstream 队列——顺序仍是先定主轴,避免并行改超时、权重、ACL 三处。与 Envoy 排障篇 对照:Envoy 把 xDS 一致性单列一轴;HAProxy 对应位置是 Reload / Runtime(文件世代与内存态)。不要把 Envoy 的 /config_dump 习惯硬套过来——HAProxy 的「世界长什么样」分散在配置文件、show * 与 leaving worker 三处。


二、五轴对照表

典型症状 优先信号 机制篇
Accept / bind 连接被拒、偶发新建失败、证书绑错端口 进程是否在听;reload 竞态;show info 中的监听与 uptime 0312
Stream / mux 卡死、半开、HTTP/2 怪异、超时方向不明 show sessshow errors;超时配置落点 0405
ACL / 路由 打到错误 backend、改写异常、限流误杀 ACL/map 内容;stick-table;httplog 中的路由结果 0608
Upstream / health 503、队列堆积、抖动上下线 server state、check 失败、队列与 maxconn 0709
Reload / Runtime 「改了没生效」、粘滞丢失、双语义 文件 vs 内存;peers;leaving worker 1112

TLS 问题常被误报成「上游挂了」:握手死在 frontend bind / SNI,backend 计数器几乎不动——先用 accept 轴与 第 10 篇 分侧,再进上游轴。

线程与调度异常(单核打满、show activity 倾斜)往往伪装成「上游变慢」。若所有 backend 延迟统计尚可,但 show activity 显示某一线程过载,应回到 第 2 篇nbthread / cpu-map / 是否有粘滞把热点打到单线程,而不是先扩容上游副本。


三、信号落点:stats、日志、sess

3.1 show info / show stat

命令 钉什么
show info 进程身份、版本、uptime、全局连接与任务概览(字段随 typed/json 模式变化)
show stat frontend / backend / server 计数器 CSV(或 JSON);吞吐、错误、状态码桶、队列
Stats HTTP 页面 同族数据的人读视图;自动化优先 socket

语义用法:

echo "show info" | socat stdio /run/haproxy/admin.sock
echo "show stat" | socat stdio /run/haproxy/admin.sock

解读原则:先看哪一层的计数器在动。Frontend 请求涨而 server 侧不动 → 多半死在 ACL/路由或本层拒绝;server 侧 DOWN / 队列涨 → 上游轴;全局 CurrConns 高但单 server 空闲 → 可能 maxconn / 队列 / 线程不均(第 2 篇)。

把 stats 刮进时序库时,注意基数:按 server 名、响应码、frontend 名打标签很容易爆炸。可观测平台治理见站内可观测性系列;本篇只要求:聚合指标用于选轴,个案用日志与 sess,两套信号不要互相冒充。

3.2 日志

option httplog / tcplog 与自定义 log-format 把终止状态、计时、backend/server 名打到 syslog。排障时日志是「一次请求的判决书」:stats 给聚合,日志给个案。勿用伪造样例代替本环境 format;字段名以 Configuration Manual 的 log-format 表为准。

终止状态码(文档中的会话状态字段)是 HAProxy 方言里最值钱的符号之一:它区分「客户端放弃」「服务器超时」「LB 自身拒绝」等。学会读本环境 format 里的那一列,比再加一块 Grafana 面板更能缩短 MTTR。对照 Nginx access 日志 时,不要假设字段同名同义。

3.3 show sess / show errors / show activity

命令 钉什么
show sess 活跃 stream 短列表;show sess <id> / all 展开 mux/缓冲细节
show errors 近期请求/响应解析错误样本(调试畸形流量)
show activity 每线程活动计数;辅助看调度是否单线程打满

show sess 成本随并发上升:生产先短格式定位,再对单一 id 深挖。输出字段多、版本敏感——本篇不虚构转储;读文档命令说明,在本机实跑后再入库。

会话级排障的常见顺序:日志里拿到终止状态与大致时间 → show stat 确认哪一层计数异常 → 若仍有活跃异常会话,再 show sess 对照 frontend/backend 名与超时方向。不要一上来对全量 show sess all:在高并发主机上,那本身就是一次负载事件。

3.4 Stick-table 与 peers

show table / show peers 落在 ACL/限流与跨进程同步轴:表满、过期、peers 断连会导致「限流突然失效」或「粘滞漂移」。与 reload 丢表的交叉见第 12 篇。

把表相关信号并进值班手册时,至少区分三类:键不存在(从未记入或已过期)、键存在但计数不符合预期(规则或采样窗口问题)、peers 显示未连接(同步面问题)。三类对应不同修复,不可都用「清表」应付——盲目 clear table 会瞬间打开放行窗口。


四、按症状走最短路径

4.1 立即 503 / 无上游

排除树:backend 名是否被 ACL 选中 → 是否有 UP server → 是否 maxconn/队列溢出 → 健康检查是否集体判死。工具顺序:日志终止码 → show stat server 行 → show servers state(若使用)→ health 轴回 09

若 frontend 计数不涨,问题可能根本没进 HAProxy(DNS、安全组、上游 LB);五轴从 accept 轴的「听没听上」开始,避免在 server 行上空转。

4.2 「配置已改」但行为旧

分叉:

  1. 只改了 Runtime → 是否连对进程?reload 是否冲掉内存态?
  2. 只改了文件未 reload → 结构面未生效。
  3. 刚 reload → leaving worker 仍服务长连接;Master CLI 分进程核对。

第四种常见分叉:改的是 map/ACL 文件,但进程内仍是旧内存映像——需要 Runtime 更新条目或 reload,取决于你们的更新路径。文件 mtime 新不等于数据面已加载。

4.3 粘滞 / 限流异常

show table 看键是否存在、计数是否符合预期;再问 peers 是否同步、reload 是否空表。勿先怀疑 LB 算法「随机」。对照 network/56 的 stick-table 菜谱时,机制失败模式以第 8 篇为准。

4.4 新建连接偶发失败

优先 accept/reload 轴:是否处于 reload 窗口、是否未走 -x/sockpair、内核是否具备 SO_REUSEPORT。对照 Management Guide 对竞态窗口的说明,而不是先调业务超时。与 第 12 篇Envoy hot-restart 一样:进程交接窗口的失败应记在运维变更上,而不是记在「随机网络抖动」上。

4.5 证书 / TLS 相关

症状:握手失败、偶发告警、HTTP 正常但 HTTPS 不行。路径:确认 bind 与 SNI 选证(accept 轴)→ 客户端协议/ALPN → 再问后端是否也做 TLS。Runtime 换证事务若中途 abort,可能留下「以为更新了」的错觉——用只读 SSL 相关 show 命令核对(命令名以 3.4.3 表为准),不要只看磁盘文件 mtime。


五、扩展边界:SPOE 与 Lua(一行)

SPOE(Stream Processing Offload Engine)与 Lua 把逻辑推出或嵌入数据面:排障时多一跳失败域(agent 超时、Lua 错误)。本系列不展开 SDK;若路径上挂了 filter/SPOE,五轴之外先确认扩展是否返回错误或阻断——然后再回 mux/ACL 轴。选型层对扩展税的讨论见 第 14 篇;产品对照见 network/60

与 Envoy Wasm/外置 auth 对照(Envoy 选型):扩展永远是「能力换排障半径」。HAProxy 的默认力量在内建 ACL/stick-table;把核心限流外包给 SPOE 前,先确认五轴清单里有没有给 agent 留观测位。

值班交接可用一页纸固化:症状 → 主轴 → 三条只读命令 → 禁止事项(例如高峰全量 show sess all、未确认 peers 前清整表)。机制篇负责「为什么」;这一页负责「半夜先干什么」。把页面挂进 runbook 后,再链回本系列对应章节,避免 runbook 与机制文各说各话。


把五轴写进事故复盘模板时,强制填写「主轴 / 排除过的轴 / 用过的只读命令 / 是否动过 Runtime」。许多复盘只写「重启恢复」,丢失了本可沉淀的机制结论。若恢复手段是 reload,必须记录是否配置了 peers、是否丢失 stick-table、leaving 是否被 hard-stop——否则下次同一症状仍会从头猜。

与可观测平台对接时,优先导出稳定、低基数的计数器(frontend 请求量、5xx、server UP/DOWN、队列深度),把高基数键(客户端 IP、完整 URI)留在采样日志。平台侧告警应指向轴,而不是指向「HAProxy 红色」——红色没有机制含义。

开放问题接到选型篇:大规模下 show sess 与全量日志是否反而淹没信号?Runtime 与 reload 混用时,排障证据链如何机器化?这些问题不在本篇关闭,但五轴提供了讨论时必须使用的名词。没有名词,值班只会留下「重启好了」三个字。

对多租户或共享入口的部署,还要在五轴之外标注「租户或监听器隔离是否失效」:一个 frontend 的 ACL 误改可能把流量打进别人的 backend。此时日志里的 frontend/backend 名字比全局 QPS 更重要。共享进程的爆炸半径是选型税的一部分,排障时先问「是否误伤邻居」,再问「上游是不是真挂了」。

命令输出入库前必须标注版本、主机与是否删减;本系列坚持不贴伪造转储,是为了避免读者把示例字段当成 3.4.3 的保证布局。字段以你本机 show info typed / 文档表为准。

五轴用熟之后,多数故障会变成「选错轴」而不是「不会敲命令」。把时间花在定轴上,比花在多开几个监控面板上更接近机制排障。

六、参考资料

规范 / 官方文档(A)

工程对照(B / 站内)

读完这篇,下一步读什么

优先读同系列或同问题的下一篇,把单篇消费变成主题集群。


By .