当伸缩触发时如何保证长连接不中断
解读
在国内云原生落地场景里,Docker 容器往往作为 Kubernetes Pod 运行,伸缩动作由 HPA 或 Cluster-Autoscaler 触发。面试官真正关心的是:
- 你是否意识到 长连接(TCP、WebSocket、gRPC 等)生命周期与 Pod 生命周期不一致;
- 能否在 Docker 镜像层、编排层、流量层 给出可落地的“零中断”方案;
- 是否熟悉 阿里 ACK、腾讯 TKE、华为 CCE 等国内发行版 的特有机制(如 SLB 优雅下线、CLB 连接复用、Service 级 Graceful Termination)。
回答必须体现“Docker 视角”,即镜像怎么配合、容器怎么退出、Registry 如何加速回滚,而不是泛泛地只讲 K8s。
知识点
- Dockerfile 信号处理:
STOPSIGNAL SIGTERM与ENTRYPOINT ["tini", "-g", "--", "yourServer"]保证容器收到 SIGTERM 后 立刻进入优雅关闭流程。 - 镜像内健康检查:
HEALTHCHECK --interval=5s --timeout=3s --retries=3 CMD /health.sh让 kubelet 精准感知 Pod Ready 状态,避免过早摘除。 - PreStop Hook 与 Docker 生命周期钩子:在
docker-compose.yml或 K8slifecycle.preStop.exec.command里执行sleep 15 && curl -X POST http://localhost:8080/gracefulShutdown,给长连接 15 s 缓冲。 - 连接迁移技术:
- SO_REUSEPORT + 无状态设计:镜像里打开
reuseport选项,使新建流量可瞬间漂到新副本; - MSE/ASM 服务网格(阿里)或 Istio 的 优雅下线接口:Sidecar 收到 SIGTERM 后通知 Envoy 把该 Pod 置为 “排空” 状态,持续 30 s 不再分配新连接,老连接自然结束。
- SO_REUSEPORT + 无状态设计:镜像里打开
- 国内云厂商 SLB 特性:
- 阿里 SLB “优雅中断” 开关:控制台设置 “连接优雅中断时长”=300 s,与容器优雅时间对齐;
- 腾讯 CLB “连接复用保持” 需关闭,否则 FIN_WAIT2 堆积。
- Registry 加速回滚:把 旧版本镜像 保留 至少两个版本标签,当新版本因长连接异常导致大量 5xx 时,HPA 回滚事件可在 30 s 内 完成
docker pull <旧镜像>并重新扩容。
答案
“我分四层保证长连接不中断:
- 镜像层:Dockerfile 里用
tini做 init,设置STOPSIGNAL SIGTERM,并把 优雅关闭脚本 写进镜像/graceful.sh,确保容器收到终止信号后 先关闭监听端口,再等待已有连接处理完。 - 容器层:在 Compose 或 K8s YAML 中增加
preStop: exec: command: ["/bin/sh", "-c", "sleep 20"],把 Pod 置为 Terminating 后继续服务 20 s,同时把 readinessProbe 的successThreshold=1改为2,防止 kubelet 过早把 Pod 从 EndpointSlice 摘除。 - 流量层:使用 阿里云 ACK 的 Terway 网络插件,配合 SLB 的 “优雅中断” 功能,设置 deregistration_delay=300 s;如果走 Ingress-Nginx,再打开
worker-shutdown-timeout: 300s,让 SLB 与 Ingress 同时感知 Pod 下线,保证 四层和七层长连接 都有 300 s 的排空窗口。 - 运维层:在 Harbor 私有仓库 里给镜像打 双标签(
v1.2.3与stable),HPA 扩容时优先拉stable,当发现新版本长连接异常升高,Argo Rollout 立即触发回滚,30 s 内 完成旧镜像重新部署,连接中断率控制在 0.01% 以下。
通过这四层,我们线上 WebSocket 在线课堂 业务在 晚高峰 5 倍弹性伸缩 时,长连接零中断,用户无感知。”
拓展思考
- 如果业务是 MQTT over TLS,如何在 Docker 镜像里嵌入 OCSP Stapling 减少 TLS 重握手时间,从而 缩短优雅窗口?
- 当集群使用 混合云架构(线下 IDC + 华为 CCE),专线抖动 导致 Registry 拉镜像超时,如何提前做 P2P 预热(如 Dragonfly)保证扩容 冷启动 <10 s?
- 在 金融场景 中,监管要求 “连接可追踪”,你是否考虑把 eBPF 探针 打进容器,实时导出 TCP 关闭事件 到 Kafka,再对接 审计系统?