【HAProxy 数据面】Seamless reload 与 soft-stop:FD 交接、排空与状态保留

💡 原文中文,约8000字,阅读约需19分钟。
📝

内容提要

HAProxy通过FD交接(-x或master-worker的sockpair)实现无缝重载,新进程接管监听,旧进程soft-stop排空存量连接,非热迁移。stick-table需peers保护,状态文件可选。相比Nginx和Envoy,三者均为“新听旧排”,HAProxy优势在Runtime API减少reload频率。生产应优先自动交接路径,控制reload频率,避免竞态窗口。

🔎

延伸解读

无缝重载的精确含义

无缝重载并非连接热迁移,而是新进程接管监听,旧进程排空存量连接。文档明确在高新建连接速率下仍可能出现少量失败,存在pause/resume竞态和listen关闭瞬间的SYN变RST窗口。工程上应选择正确的交接路径(-x或master-worker自动sockpair),并控制reload频率,将失败压入噪声,而非宣称绝对无感。

FD交接路径选择

FD交接有三种路径:非master-worker下需配置expose-fd listeners并使用-x;master-worker下自动使用sockpair@,无需expose-fd;若无-x则退化为pause/resume竞态,存在毫秒级窗口。生产应优先自动交接路径,并注意容器场景下若先杀旧容器再起新容器,则属于滚动重建而非无缝重载。

soft-stop与状态保留

soft-stop期间旧进程继续服务存量连接,超长会话会拉长双进程共存窗口,需用hard-stop-after设上限。stick-table默认在reload时清空,需通过peers保护;Runtime改动的权重等状态除非写入state文件否则丢失。发布系统应关注leaving worker状态,避免过早标绿。

与Nginx/Envoy的对比

三者均为'新听旧排',非连接热迁移。HAProxy优势在于Runtime API可减少reload频率,Envoy则依赖xDS,Nginx多数变更仍需reload。若组织变更极频繁且需ACK语义,HAProxy的文件+Runtime模型可能先触顶;若以结构变更为主,seamless路径足够支撑经典LB运维。

Q&A

HAProxy seamless reload 是如何实现新老进程 FD 交接的?

HAProxy 通过 -x 选项或 master-worker 模式下的 sockpair@ 机制实现 FD 交接。非 master-worker 时,新进程用 -x 连接旧进程的 stats socket(需配置 expose-fd listeners)取回 listening FD;master-worker 模式下,master 自动用 sockpair@ 直连 worker 取回 FD,无需 expose-fd。

HAProxy soft-stop 和 hard stop 有什么区别?

soft-stop(SIGUSR1)是优雅停止:旧进程停止 accept 新连接,但继续处理存量连接直到排空后退出;hard stop(SIGTERM)是立即终止,切断所有连接。

HAProxy seamless reload 能保证不丢连接吗?

不能保证绝对不丢。seamless reload 的“不丢连接”是指存量连接留在旧进程排空,而非迁移到新进程。在高新建连接速率下仍可能出现少量失败,存在 pause/resume 竞态和 listen 关闭瞬间的 RST 窗口。工程上应选择正确的交接路径(-x/sockpair)并控制 reload 频率来降低失败。

HAProxy reload 时 stick-table 数据会保留吗?

默认情况下,reload 后 stick-table 条目会被清空。要保留数据,需要配置 peers 段并将本机列为 peer,通过 peers 协议同步;或者使用 state file 保存和加载。未配置 peers 时,限流桶和粘滞数据在 reload 瞬间归零。

HAProxy seamless reload 与 Nginx reload、Envoy hot-restart 有何异同?

三者都是“新听旧排”模式:新进程接管监听,旧进程排空存量连接,不迁移连接。HAProxy 的优势在于日常运维可通过 Runtime API 减少 reload 频率;Envoy 主要用 xDS 动态配置,hot-restart 是例外;Nginx 多数变更仍需 reload。

HAProxy reload 时旧进程如何排空存量连接?

旧进程收到 SIGUSR1 后停止 accept 新连接,继续服务已建立的 stream 直到自然结束,然后退出。超长连接(如 WebSocket)会拉长排空时间,需用 hard-stop-after 设置上限,避免旧进程长期占用资源。

HAProxy 在无 -x 或 master-worker 时如何避免端口冲突?

无 -x 时,新进程无法直接继承 FD,会走 pause/resume 路径:先让旧进程 pause(SIGTTOU),新进程 bind,失败则 resume(SIGTTIN)。这存在毫秒级竞态窗口,高并发下可能失败。现代 Linux 的 SO_REUSEPORT 可缩小竞态,但生产应优先使用 -x 或 master-worker 自动交接。

HAProxy reload 时 Runtime API 修改的配置会保留吗?

不会。Runtime API 的修改只存在于当前进程内存中,reload 后新进程按配置文件启动,Runtime 修改会丢失,除非通过 state file 保存并加载。

🏷️

标签

➡️

继续阅读