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

💡 原文中文,约5600字,阅读约需14分钟。
📝

内容提要

Envoy热重启通过新进程接管监听、旧进程排空连接实现,连接不迁移。使用UDS RPC和共享内存协调统计,参数包括drain-time和parent-shutdown-time。xDS可解决的变更优先用xDS,仅二进制升级或不可热替换项才用热重启。需注意长连接超时、并发降低等问题。

🔎

延伸解读

热重启不是连接迁移

热重启的核心是“新进程接监听,旧进程排空”,现有连接不会转移到新进程。这意味着长连接必须在排空窗口内结束,否则会被强制关闭。对于HTTP/2,可通过GOAWAY让客户端将新流转到子进程,但WebSocket或长轮询若超过drain-time-s仍会被切断。因此,热重启适合二进制升级或无法热替换的场景,而非追求连接无缝迁移。

drain与parent shutdown的时间关系

drain-time-s控制连接排空窗口,默认600秒;parent-shutdown-time-s控制父进程强制退出时间,默认900秒,必须大于drain时间。若设置不当,父进程可能过早被杀,导致连接粗暴断开。运维需根据实际连接时长分布调整这两个参数,边缘代理常拉长drain,而服务网格sidecar可缩短至分钟级。

热重启的适用边界

文章强调,能通过xDS解决的变更应优先使用xDS,热重启仅用于二进制升级或无法热替换的进程状态。例如,路由权重、endpoint变更走xDS,监听器增删改走LDS,而Envoy版本升级或无法热替换的admin/tracing配置才需要热重启。证书轮转若已接SDS则无需热重启。

热重启的失败模式与注意事项

热重启存在多种失败模式:epoch或共享内存不匹配会导致子进程启动失败;parent-shutdown-time小于drain-time会过早杀父进程;长连接超过drain窗口会中断业务;concurrency下调可能丢失accept队列中的连接;多实例共用base-id会冲突。此外,热重启期间更新socket_options不受支持,需全量重启或走LDS路径。

Q&A

Envoy 热重启时,现有连接如何处理?

Envoy 热重启时,现有连接不会迁移到新进程,而是在旧进程(父进程)中排空(drain),在排空窗口内优雅关闭,超时未结束的连接会被强制终止。

Envoy 热重启中,新旧进程如何协调和传递统计信息?

Envoy 热重启中,新旧进程通过 Unix domain socket (UDS) 上的 RPC 通信,旧进程的计数器(counter)和 gauge 通过 UDS 传给新进程(标记为 NeverImport 的 gauge 除外)。此外,它们通过共享内存区域协调版本信息、原始统计存储和跨进程锁。

Envoy 热重启中,--drain-time-s 和 --parent-shutdown-time-s 参数的作用是什么?

--drain-time-s 指定连接排空窗口,默认 600 秒,用于优雅关闭旧连接;--parent-shutdown-time-s 指定子进程等待后强制父进程退出的时间,默认 900 秒,应大于 drain 时间。

Envoy 热重启与 xDS 热更新有何区别?

Envoy 热重启是跨进程的,新进程接管监听,旧进程排空连接,连接不迁移;而 xDS 热更新是在单进程内替换对象,连接通常保留。xDS 适用于路由、端点等配置变更,热重启适用于二进制升级或无法热替换的项。

Envoy 热重启时,如果 concurrency 降低会有什么影响?

如果热重启时 concurrency 降低,旧 worker 的 accept 队列上可能丢失连接;concurrency 升高则不会因此丢连接。

Envoy 热重启时,长连接超过 drain 时间会怎样?

如果长连接超过 --drain-time-s 指定的排空窗口,父进程会强制关闭这些连接,导致业务中断。

Envoy 热重启时,如何避免共享内存冲突?

在同一宿主机运行多套独立 Envoy 时,使用 --base-id 或 --use-dynamic-base-id 隔离共享内存,避免冲突。

🏷️

标签

➡️

继续阅读