土法炼钢兴趣小组的算法知识备份

【Envoy 数据面】Hot restart 与 drain:共享内存、父子交接与连接排空

文章导航

分类入口
networkproxy
标签入口
#envoy#hot-restart#drain#shared-memory#listener#xds#operations

目录

第 11 篇 的结论是:多数 Listener/Cluster/Route/Secret 变更应走 xDS + warming,而不是重启进程。仍有一类变更必须动二进制或无法热替换的进程状态——这时进入 Hot restart:新进程起来、旧进程 drain,现有连接不迁移

本文钉 Hot restart 架构、drain / parent shutdown 时间线,以及它与 LDS drain、纯 xDS 更新的边界。扩展过滤器如何挂在请求路径上见 第 13 篇

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

篇目 核心内容
第 11 篇 · Warming / SDS xDS 热更新边界
第 12 篇 · Hot restart / drain 共享内存、交接、排空
第 13 篇 · 扩展边界 Wasm / Lua / ext_authz / ratelimit

版本锚定:Envoy v1.39.0 Hot restartCommand line options--drain-time-s / --parent-shutdown-time-s / --restart-epoch)。Windows 不支持 Hot restart。无伪造重启日志。


一、Hot restart 解决什么问题

官方表述:Envoy 可以在 drain 过程中完整重载自身(代码与配置),且不在排空期间主动丢掉仍可优雅关闭的连接。但:

现有连接不会转移到新进程;它们必须在 drain 内结束,否则被终止。

因此 Hot restart 不是「连接热迁移」,而是「新进程接 listen,旧进程排空」。与 Nginx reload 的父子模型同族,但 Envoy 额外用共享内存对齐多进程统计,并用 UDS 上的 RPC 协调。

相对 第 11 篇 的 xDS 路径:

xDS 热更新 Hot restart
进程 单进程内对象替换 父子双进程重叠
连接 通常保留;LDS 变更触发 listener drain 迁移;旧连接在父进程排空
典型触发 LDS/RDS/CDS/EDS/SDS 二进制升级、无法热替换项
统计 同进程连续 经共享内存 / UDS 交接对齐

二、架构:UDS RPC 与共享内存

v1.39.0 Hot restart 文档给出的骨架:

  1. 两个活跃进程通过 Unix domain socket 上的基础 RPC 通信。
  2. 旧进程的 counter 经 UDS 发给新进程;gauge 也会传输,但标记 NeverImport 的除外。重启结束后,从旧进程导入的 gauge 会被清理;server.hot_restart_generation 这类特殊 gauge 保留。
  3. 新进程先完成初始化(加载配置、初始服务发现与健康检查等),再向旧进程索取 listen socket 副本。
  4. 新进程开始 listen,然后通知旧进程 开始 drain
  5. drain 结束后(通常),新进程通知旧进程 关闭;剩余连到旧进程的连接被关掉。

Matt Klein 的设计文(B 级,机制与文档一致)补充:共享内存区承载版本信息、原始 stat 存储与少量跨进程锁;epoch 0 创建区域,后续 epoch attach。布局或 RPC 协议不兼容时热重启失败并给出明确错误——这是「不能跨任意大版本无脑 hot restart」的物理原因。

sequenceDiagram
  participant Parent as ParentEnvoy
  participant Child as ChildEnvoy
  Note over Child: Full init: config, SDS/EDS, HC
  Child->>Parent: Request listen sockets
  Parent-->>Child: Pass sockets by worker index
  Child->>Child: Start accepting
  Child->>Parent: Begin drain
  Note over Parent: Graceful close; more aggressive over time
  Child->>Parent: Shutdown parent
  Parent->>Parent: Exit; remaining conns closed

容器边界:文档明确 Hot restart 设计为父子可在不同容器,只要 UDS 可达。同一宿主机跑多套独立 Envoy 时,用 --base-id--use-dynamic-base-id 隔离共享内存,避免冲突。


三、时间线:epoch、drain、parent shutdown

参数 默认(文档) 含义
--restart-epoch 0(首次) 第几次热重启;决定创建还是 attach 共享内存。包装器常设 RESTART_EPOCH
--drain-time-s 600s Hot restart LDS 修改/删除 Listener 时的连接排空窗口
--parent-shutdown-time-s 900s 子进程等待后强制父进程退出;应 大于 drain 时间
--base-id (默认单套) 多实例共享内存命名空间

Drain 行为要点:

Socket 处理(Linux):默认 reuse_port;Hot restart 时按 worker index 把 socket 传给新进程,避免 drain 进程 accept 队列里的连接被丢。注意:若热重启时 concurrency 降低,旧 worker 的 accept 队列上可能丢连接;concurrency 升高则不会因此丢。

限制:Hot restart 期间更新 Listener 的 socket_options 不受支持,子进程沿用父进程选项;要改则全量重启或走 LDS 更新路径。

3.1 连接排空在数据面上意味着什么

「不丢连接」在文档里的精确含义是:drain 窗口内尽量优雅结束,而不是把 TCP 会话 splice 到子进程。对 HTTP/1,常见路径是不再接受新请求并关闭空闲连接;对 HTTP/2,可配合 GOAWAY 让客户端把新流转到已在听的子进程。WebSocket / 长轮询若超过 --drain-time-s,仍会被父进程关闭——这是 Hot restart 相对纯 RDS 权重切换的硬代价。

边缘代理往往把 drain 拉长(文档举例可达数分钟到默认 10 分钟量级);服务网格 sidecar 则可把 drain 与 parent shutdown 缩到分钟内,因为实例可被编排层并行替换。口径必须以本环境连接时长分布为准,本篇不写未测的「推荐秒数」。


四、与 xDS-only、LDS drain 的对照

三者共享「排空」一词,层级不同:

xDS object swap     → 同进程;Cluster 原子替换;Route 立即对新建请求可见
LDS listener drain  → 同进程;旧 listener 连接排空(--drain-time-s)
Hot restart drain   → 跨进程;父进程排空;listen 已在子进程
变更类型 推荐路径 为何
路由权重、endpoint、多数 filter 配置 xDS 无双进程;warming 可控
监听器增删改 LDS(含 drain) 仍同进程;无需换二进制
Envoy 版本升级、无法热替换的 admin/tracing 等 Hot restart 或滚动重建 必须新代码/新进程状态
仅换证书且已接 SDS SDS 见第 11 篇;不必为换证 hot restart

动态配置总览的原话意图:引入 LDS 后,几乎所有方面都可动态配置;Hot restart 应留给极少配置变更、证书场景(未走 SDS 时)或二进制更新。


五、失败模式与运维含义

模式 现象 处理方向
epoch / 共享内存不匹配 子进程起不来或协议错误 对齐版本;必要时冷启动
parent-shutdown-timedrain-time 父进程被过早杀掉,连接粗暴断开 拉大 parent shutdown
长连接 > drain 窗口 业务中断 调窗口,或先切流量再重启
concurrency 下调 accept 队列丢连接 避免在热重启时降并发
多实例共用 base-id 共享内存冲突 每套实例独立 base-id

源码发行版带 restarter/hot-restarter.py 示例,可与 monit/runit 等进程管理配合;生产上常见的是编排层滚动 + 或发行版自带的 hot restart wrapper,本篇不展开具体发行包装。


六、争论与开放问题

争论 A B
Hot restart vs 滚动换 Pod 单机原地升级、统计连续 编排更简单、失败域清晰
长 drain vs 短 drain 边缘长连接友好 网格中东占用双倍内存窗口

开放问题:在 sidecar 密集节点上,Hot restart 双进程重叠的内存峰值与「直接杀旧 Pod」相比,哪条对节点水位更友好——取决于连接时长分布与编排并行度,需按环境实测。


七、参考资料

规范 / 官方文档(A)

源码 / 设计(A/B)

站内对照

实验台账


八、小结

  1. Hot restart = 子进程接 listen + 父进程 drain,连接不迁移。
  2. UDS RPC + 共享内存对齐协调与统计;--restart-epoch / --base-id 决定 attach 语义。
  3. --drain-time-s < --parent-shutdown-time-s;LDS 变更与热重启共用 drain 时间旋语义。
  4. 能 xDS 解决的不要 hot restart;二进制与不可热替换项才上进程级交接。

系列目录 · 上一篇:Warming、SDS 与热更新 · 下一篇:扩展边界

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-08-10 · network / proxy

Envoy / 数据面代理内核:从 Listener 到 xDS

补齐站内 Envoy 单篇地图与 Mesh/网关选型之间的数据面内核层:Main/Worker、FilterChainMatch、HCM、Cluster/连接池、xDS warming 与 Hot restart,并以排障与选型收束。


By .