优雅停机与连接 Drain 工程实践:从 Linux 信号到 Kubernetes Pod 的完整链路
生产环境中,一次失败的优雅停机可能导致客户端看到 502、数据库连接半开、消息重复消费,甚至分布式事务悬挂。本文从 Linux 信号处理出发,完整覆盖 TCP 半关闭、进程生命周期管理、连接池 Drain、Kubernetes Pod 终止链路、消息队列的 unacked 回收,到 Rust/Go/Java 的具体实现,给出可落地的生产级 Checklist。
一、问题的真正复杂度
很多工程师对\"优雅停机\"的理解就是\"捕获 SIGTERM 然后 exit(0)\",但在生产级系统中,真正的挑战分布在多个层面:
- 网络层:正在飞行的请求怎么办?TCP 连接是 RST 还是 FIN?
- 应用层:正在执行的 Handler 能否完成?连接池中的借出连接如何归还?
- 中间件层:Redis/MySQL/消息队列的 client 是否注册了 close hook?编排层**:Kubernetes 的 preStop、terminationGracePeriodSeconds、Service Endpoint 摘除时序是否正确?
任何一个环节遗漏,都会导致\"看似优雅,实则翻车\"。
二、Linux 信号处理:被忽视的细节
2.1 signal() vs sigaction()
永远使用 sigaction(),不要用 signal()。原因有三:
signal()在不同 UNIX 平台行为不一致(System V 语义 vs BSD 语义),sigaction()是 POSIX 标准sigaction()可以指定SA_RESTART标志,让被信号中断的系统调用自动重启(避免EINTR处理遗漏)sigaction()通过SA_SIGINFO获取发送者 PID、UID 等上下文信息
#include

发表评论 取消回复