【Envoy 数据面】Hot restart 与 drain:共享内存、父子交接与连接排空
内容提要
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 隔离共享内存,避免冲突。