文章 587
评论 5
浏览 230032
SpringBoot 微服务优雅停机失败:K8s 滚动更新丢请求?PreStop 钩子+连接排空机制实战

SpringBoot 微服务优雅停机失败:K8s 滚动更新丢请求?PreStop 钩子+连接排空机制实战

公司 K8s 每次发版都有几个 502。查了监控,规律很明显——总是在旧 Pod 被 kill 的那几秒。原来是 K8s 滚动更新的时候,先发 SIGTERM 给旧 Pod,然后立刻把流量切到新 Pod。但旧 Pod 上还有正在处理的请求——SIGTERM 一来,进程直接退,请求半途而废。前端就 502 了。 Spring Boot 2.3 以后支持优雅停机,但光配 server.shutdown=graceful 还不够。K8s 的流量切换和 Pod 停机之间有时间差——你得让 Pod 在被 kill 之前有足够时间把正在处理的请求跑完。 问题拆解:K8s 发版一分钟内发生了什么 K8s 滚动更新流程: T+0s 新 Pod 创建,等待就绪 T+5s 新 Pod Ready → 加入 Service Endpoint T+5s K8s 发 SIGTERM 给旧 Pod T+5s 旧 Pod 上的请求还在跑 → 但 Service 已经不分配新请求了 T+5s 旧 Pod 收到 SIGTERM → Spring 开始优雅停机 ├─ 不再接受新请求 ├─ 等待正在处理的请求完成(30....

WebSocket 优雅停机与连接迁移:服务发版用户频繁掉线?平滑过渡 + 状态保持方案!

WebSocket 优雅停机与连接迁移:服务发版用户频繁掉线?平滑过渡 + 状态保持方案!

公司的在线客服系统用的是 WebSocket。每次发版滚动更新,旧 Pod 一停,挂在上面的几千个 WebSocket 连接全断。前端虽然做了自动重连,但重连期间用户发了一条消息,没收到回复,以为客服不理他,直接给了差评。更糟糕的是,客服正在输入的内容也丢了——WebSocket 断了,会话状态没了。 WebSocket 跟 HTTP 不一样。HTTP 是无状态的,请求断了重试一次就好。WebSocket 是长连接,一旦断了,连接上的状态全丢。发版又是必然事件——你不能为了 WebSocket 永远不发版。 今天聊聊怎么让 WebSocket 在服务发版时平滑过渡,不让用户感知到断线。 WebSocket 发版的三个痛点 滚动更新时,K8s 或者运维平台会给旧 Pod 发 SIGTERM 信号,然后等一段时间(默认 30 秒)后 SIGKILL。WebSocket 没有 HTTP 那样的负载均衡重试机制,Pod 一死连接直接断。 三个痛点: 连接断开——旧 Pod 停了,上面的 WebSocket 连接瞬间全断。用户端要么看到连接断开提示,要么消息发不出去。 状态丢失——客服正在输入....

服务端开发博客:后端架构、高并发、性能优化与微服务实战教程