第 10 篇 把 TLS 终结与透传钉在请求路径上。运维下一问往往不是「怎么配」,而是:权重、上下线、限流计数能不能在不停流量下改;哪些变更必须走配置文件 + reload。
本文钉 Runtime API(stats socket / Unix Socket
commands)的热改面与结构面分界,以及
master-worker 下的 Master
CLI。命令只写语义与调用形态,不粘贴伪造的
show info / show sess
输出。菜谱级脚本与运维手法见站内 HAProxy
工程(network/56);进程交接与 FD 语义见 第 12
篇。
本文是「HAProxy / 数据面代理内核」系列第 11 篇(共 14 篇)。→ 系列目录
篇目 核心内容 第 10 篇 · SSL/TLS 终结 vs 透传 第 11 篇 · Runtime API 热改范围 vs reload 第 12 篇 · Seamless reload FD 交接与 soft-stop
版本锚定:HAProxy 3.4.3 Management Guide §9(Unix Socket commands / Master CLI)。热改结果在内存中生效,默认不写回配置文件;reload 后未持久化的 Runtime 变更会丢失,除非另有 state file / peers 等机制。
一、两个运维平面:热改 vs 结构变更
HAProxy 的配置模型仍是「启动时解析、进程生命周期内结构基本固定」。Runtime API 补的是在既有结构上改运行态,而不是把整个配置树变成 xDS 式资源。
flowchart TD
change["Config change request"] --> q{"Structural?"}
q -->|"no: weight / state / map entry"| rt["Runtime API on stats socket"]
q -->|"yes: new bind / frontend / rule tree"| file["Edit cfg + seamless reload"]
rt --> mem["In-memory only until reload"]
file --> handoff["New workers + FD handoff"]
| 平面 | 载体 | 典型操作 | 持久性 |
|---|---|---|---|
| Runtime | stats socket(level admin) |
改权重、server state、clear table、add/del map/acl 条目 | 内存;reload 默认冲掉 |
| 结构 | 配置文件 + reload | 新 bind、新 frontend/backend
段、改写规则树拓扑 |
文件;由新进程解析 |
常见误区:把 Runtime 当成「迷你控制面」。它没有 ACK
树、没有 warming 依赖图;成功与否以命令返回与后续
show *
语义为准,而不是以外部编排的「已推送」文案为准。对照 API
驱动范式见 Envoy
选型收束;网关产品层横向对比见 network/60。
谱系上,这是「静态配置文件 + 窄动态面」传统:进程启动时把 frontend/backend/server 对象图固定下来,再用 socket 命令改对象上的可变字段。它与 Envoy 的 xDS 资源树不是同一抽象层次——后者把依赖、warming、ACK 做成协议;前者把运维速度押在「少 reload、多改内存」。两者都能「不停流量改行为」,但失败模式不同:Runtime 错了立刻作用在当前进程;xDS 错了可能停在 NACK/warming(见 Envoy 系列)。选型时先问组织有没有控制面编制,再问要不要 HAProxy 这层热改,而不是反过来。
权限模型也属于平面分界的一部分。stats socket
的 level(user /
operator /
admin)决定能看还是能改;生产自动化若共用一个
admin
socket,等于把摘流与清表能力交给每一条流水线。更稳妥的做法是:只读监控走低权限
socket,变更走受控的 admin 通道并审计命令文本。TCP 暴露
stats socket 在文档里被标为危险默认——本系列默认假设 UNIX
域套接字 + 文件系统权限。
二、可热改:服务器、表、ACL/Map、前端开关
下列能力以 Management Guide 3.4.3 Unix Socket commands 为准(名称以文档命令表为准;参数细节随 patch 核对)。
2.1 服务器运行态
| 命令族 | 语义 |
|---|---|
set weight /
set server … weight |
改 LB 权重;影响后续调度,不迁移已有连接 |
enable server /
disable server |
启用 / 维护下线(经典写法) |
set server … state {ready\|drain\|maint} |
ready 接新流量;drain
不再接新请求但仍服务存量;maint 停流量 |
set server … addr [port] |
改地址/端口(动态后端场景) |
add server / del server |
在已有、且满足动态算法约束的 backend
上增删 server;del 前通常需 maint 且无残留
stream |
add server
的文档约束值得单独记住:动态创建的 server
不会在 reload
后自动复现,除非配置文件里也写了对应条目(或配合 state
持久化流程)。热加只解决「当前进程内扩容」,不替代 Git
里的真相源。
drain 与 maint
的差别常被脚本写反:drain
适合发布前摘流——存量连接继续结束,调度器不再把新请求打上去;maint
适合故障隔离或即将
del server——更彻底地停流量。权重改成 \(0\) 与进入 drain
在调度结果上可能相近,但状态机与健康检查交互不同,自动化应以
state 命令为准,而不是只改百分比。agent-check
启用时,agent 回报可能再次改变 server
状态;文档要求删除前先处理好 agent,否则会出现「刚 maint
又被 agent 拉起」的竞态。
与健康检查的交叉:Runtime 把 server 标
UP/ready,并不保证检查探针定义本身正确——探针参数多数仍属结构面,见
第 9
篇。排障时若「Runtime 已 enable 但仍无流量」,先看 check
是否仍判死,再看 ACL 是否选到该 backend。
2.2 Stick-table 与限流状态
| 命令 | 语义 |
|---|---|
show table |
列出表或转储条目(键、计数器、过期) |
clear table … |
按 key / data 条件 / ptr 清条目 |
限流、粘滞、封禁若落在
stick-table,clear table
是运行态急救,不是改规则本身。表类型、容量与
peers 复制见 第 8
篇;reload 时表是否保留取决于 peers 配置,见第 12
篇。
2.3 ACL / Map 条目(不是规则树)
add acl / del acl /
clear acl、add map /
set map / del map
等改的是已声明 pattern
文件或内联表的内容,不是把
use_backend if … 拓扑重写一遍。
| 能热改 | 仍需 reload |
|---|---|
| 白名单 IP 增删、map 键值更新 | 新增 ACL 表达式、改匹配字段、改
http-request 动作链结构 |
| 对已有 map 做 prepare/commit 版本切换 | 新 frontend、新 backend 名、新 stick 规则拓扑 |
prepare / commit
一类版本化更新,是为了让大表替换接近原子:先在新版本填条目,再切换命中版本,避免「清表到填完」窗口里策略空洞。具体命令参数以
3.4.3 命令表为准;工程上要把它当成事务,而不是一串互不相关的
add。
SSL 证书热更新(set ssl cert 与 commit/abort
事务)属于另一条窄动态面:能换 PEM 内容,不等于能随意改
bind
上的证书选择拓扑。证书运维手册不在本系列展开;只需记住——能
commit 的走事务命令,文档写明 reload
后不恢复的,必须回写配置。
2.4 Frontend 开关与 maxconn
disable frontend /
enable frontend、set maxconn frontend
等可在不停进程的情况下关掉入口或调并发上限。disable frontend
会释放该 frontend
的监听绑定语义(文档描述为停止接受),常用于事故隔离;它不等于增加一个新的
bind 地址。
命令形态(语义示例,路径以本机 stats socket
为准):
echo "set server api/s1 weight 50%" | socat stdio /run/haproxy/admin.sock
echo "set server api/s1 state drain" | socat stdio /run/haproxy/admin.sock
echo "clear table http_front key 10.0.1.55" | socat stdio /run/haproxy/admin.sock
echo "show info" | socat stdio /run/haproxy/admin.sockshow info / show stat /
show sess / show table
用于核对进程身份、计数器与会话;本系列不粘贴未在本机实跑的输出。字段含义与排障落点见
第
13 篇;具体脚本见 network/56。
三、必须 reload:结构、绑定、规则拓扑
下列变更默认写文件并走 seamless reload(-sf
/ master-worker SIGUSR2),而不是指望一条
CLI:
- 新的
bind/ 监听地址族 / 端口拓扑(含多数 SSL bind 结构变更)。 - 新增或删除 frontend / backend / listen 段(结构性增删;个别实验性/受限的动态 backend 命令不改变「配置文件仍是真相源」这一运维模型)。
- ACL /
use_backend/http-request规则树的结构改写(字段、动作、顺序),而不只是 pattern 内容。 - 全局调优与多数
tune.*、线程组布局、日志目标拓扑等进程级参数。 - 健康检查探针定义、多数 filter/SPOE 挂载点等与解析期绑定的对象。
Runtime: 改「已有对象的运行态与表内容」
Reload: 改「对象图本身与 bind 拓扑」
边界上的灰色地带(如部分 SSL 证书热更新、动态
server)仍以 3.4.3 命令表 + Configuration
Manual 为准:能 commit
的走事务命令;文档写明「reload 后不恢复」的,必须回写配置或
state 流程。
与 Nginx 深度(network/55) 对照:Nginx 的动态面更窄,多数变更直接等同 reload;HAProxy 把「服务器与表」从 reload 里拆了出来,但没有把结构面拆成可 ACK 的资源树——那是 Envoy/xDS 的格。进程级交接本身(旧进程如何 soft-stop、FD 如何交接)见 第 12 篇;其时间线与 Envoy hot-restart 同属「新听旧排」家族,但日常触发频率因 Runtime 面宽度而不同。
实践上还有一类「看起来像结构、其实可热改」的错觉:例如「加一个后端机器」。若
backend 与动态算法已在文件里声明,且用
add server(并接受 reload
后须回写的纪律),可以不 reload;若要的是新的 backend
名、新的 balance 算法族、或新的
use_backend 分支,则必须
reload。判断口诀:改对象属性 → Runtime;改对象图 →
文件。
四、Master CLI:看得到 leaving worker
global 的 master-worker(或
-W)下,可用 -S 绑定
Master CLI(Management Guide
§9.4)。它面向所有进程:当前 worker、以及
soft-stop 尚未退出的 leaving worker。
要点:
- 推荐绑本地 UNIX socket;权限等同运维面,需隔离。
- Master CLI 不能用来做 seamless reload 的 listen FD 取回(文档明确:该 socket 不可用于 retrieve listening sockets)。
- 用
@!PID/@相对编号前缀把命令投递到指定进程;show proc列出 master / worker / leaving。 - 排障时:reload 窗口若出现「新旧语义并存」,应分别对
current 与 leaving 执行只读
show *,避免只连默认 worker socket 看到一半世界。
# Master CLI:列出进程,再对指定 worker 发命令(路径示例)
echo "show proc" | socat stdio /run/haproxy-master.sock
echo "@!11955 show info" | socat stdio /run/haproxy-master.sockWorker 上的 stats socket
仍是日常自动化首选;Master CLI
是生命周期与多进程可见性的补丁,不是替代整个
Runtime 菜谱。
reload 窗口里若只连 worker 的 admin.sock,可能连到
current,也可能在多 socket
场景下连到非预期进程——文档提醒多进程共享同类 socket
时「谁捡起请求谁回答」。因此涉及「刚 reload」的核对,优先
Master CLI 显式选 PID,再发只读命令。写变更时更要小心:对
leaving worker 做 set weight
往往无意义(它已在排空),对 current
的变更又不会自动回写文件。
五、运维模型:何时 Runtime、何时 reload
| 场景 | 优先路径 | 原因 |
|---|---|---|
| 单机摘流、改权重、清限流键 | Runtime | 无双进程窗口;秒级生效 |
| 扩容动态 server 且可回写 cfg/state | Runtime + 持久化纪律 | 避免 reload 后幽灵节点 |
| 新域名 bind、新路由树、改 LB 算法结构 | 文件 + reload | 结构只能由解析器重建 |
| 二进制升级、全局线程布局 | reload / 滚动 | 必须新进程镜像 |
争论点(工程,非跑分):频繁 reload 会引入文档已记载的毫秒级 bind 竞态窗口与 backlog 丢连接可能(见第 12 篇);过度依赖 Runtime 则使磁盘配置与内存真相分叉,事故时「Git 与线上不一致」。健康模型是:结构变更走文件;运行态急救走 Runtime;关键 Runtime 变更有回写或 state 门禁。
一个可操作的门禁草案(本机落地时再改成脚本,此处只定语义):结构合并进主分支后必须
haproxy -c 通过再 reload;Runtime
变更若影响容量规划(权重、maxconn、动态
server),必须在变更流水线留下命令审计,并在约定时间内回写配置或刷新
state file;任何「只存在于内存」的长期状态视为债务。对照 network/56
的运维章节可把门禁落成具体命令,但不要把菜谱复制进机制文。
开放衔接:stick-table 在热清与 peers 复制下的一致性、以及「reload 与 Runtime 混用」的可观测缺口,收在 第 14 篇。
六、参考资料
规范 / 官方文档(A)
- HAProxy 3.4.3 Management
Guide:
https://docs.haproxy.org/3.4/management.html— §9 Unix Socket commands;§9.4 Master CLI;-S/-x/-sf选项说明。 - HAProxy 3.4.x Configuration
Manual:
stats socket、master-worker、level、expose-fd listeners。
工程对照(B)
- HAProxy Technologies 博客:Dynamic configuration with the HAProxy Runtime API(热改能力清单,作辅助,不替代命令表)。
- 站内 network/56:Runtime 菜谱与脚本。
- 站内 Envoy 16:API 驱动 vs 文件/Runtime 驱动排除树。
源码锚点(A,路径级)
haproxy/haproxytag v3.4.3:stats/cli 命令注册与 server 动态增删逻辑(核对命令名时以文档为准,源码作实现旁证)。
读完这篇,下一步读什么
优先读同系列或同问题的下一篇,把单篇消费变成主题集群。
【HAProxy 数据面】选型收束:机制排除树与系列开放问题
用机制排除树收束 HAProxy 相对 Nginx、Envoy、eBPF 的选型;回收本系列阅读路径,并列出 stick-table 规模、QUIC/H3 成熟度、reload 与 Runtime 混用可观测等开放问题。
【HAProxy 数据面】ACL / 规则引擎:求值顺序、副作用与 stick-table 耦合
把 ACL 与 http-request / use_backend 当作数据面机制:说明连接期到 L7 的求值顺序、动作副作用如何改写后续条件,以及与 stick-table 限流/标记的耦合点;不写 ACL 关键字百科。
【HAProxy 数据面】Stick-table:键类型、容量、跨线程可见性与 peers/reload
说明 stick-table 的键类型、size/expire/store、nbthread 共享内存与 nbproc 不共享的边界,以及 peers 复制与 reload 继承;覆盖表满等容量失败模式。
【HAProxy 数据面】Seamless reload 与 soft-stop:FD 交接、排空与状态保留
按 HAProxy 3.4.3 Management Guide 拆解 -x / expose-fd listeners / master-worker sockpair 的 listen FD 交接、SIGUSR1 soft-stop 排空,以及 stick-table/peers 在 reload 下的保留边界;对照 Nginx 与 Envoy hot-restart。