开始前,会这些就够了
- 知道服务可以有多个实例
- 知道请求可能需要等待
遇到不熟悉的词,先看这 5 个解释
- 进程
- 进程是正在执行的程序及其所需资源形成的运行单位。以常见桌面系统为例,它有自己的地址空间、打开的资源和线程,操作系统据此管理程序的运行。
- 线程
- 线程是进程中被安排执行的一条运行路线。同一进程可以有多个线程,共用部分数据和资源,同时各自保存执行位置与调用记录,因此协作时要留意互相影响。
- 超时
- 调用方为一次等待设置上限,超过时间还没拿到所需结果,就结束这次等待并报告超时;这样能限制资源占用,但并没有自动确认对方最终做到了哪一步。
- 负载均衡
- 在多个可处理请求的后端之间,按轮流、权重或其他规则分配流量,减少请求集中到单个实例的情况;分发依据和健康检查决定实际送给谁。
- 容器
- 容器是根据镜像创建的隔离运行环境,用来运行应用进程;镜像带上应用文件和所需依赖,便于重复部署。同一镜像可以创建多个容器,容器也可以处于停止状态。
假设订单服务准备发布新版本,旧实例手里还有一个需要数秒才能完成的请求。立刻杀进程可能让客户端只看到断开;一直等所有工作结束,又可能被一个永远不结束的请求拖住。优雅停机是在有限时间里协调收尾,不是承诺任何故障下都零中断。
先少接新请求,再处理已经接下的
可以把流程拆成三阶段:通知入口不要再把常规新请求送来;让已经接下的请求在期限内完成;在平台强制终止之前,预留时间记录未完成状态并退出。实际平台中,摘除流量和应用关闭可能并行发生,不应想象成一个瞬间完成的全局开关。
长连接、代理已经选好的请求以及传播延迟,都可能使停机开始后仍有请求到达。应用要有自己的拒绝新工作规则,入口也要支持连接排空。只把健康检查改成失败,却继续无限接受工作,或只关应用而不考虑入口,都可能在切换时暴露空档。
应用与平台的时间预算要对得上
Spring Boot 3.5 文档说明,优雅关闭给已有请求完成的时间,并限制新请求;每个关闭阶段的等待可通过 spring.lifecycle.timeout-per-shutdown-phase 设置。不同内嵌服务器拒绝新请求的方式不同,不能要求所有框架都返回同一个状态码。
Kubernetes 普通 Pod 终止流程还包含 preStop、终止信号与平台的终止期限。preStop 也消耗这个收尾时间,不能把它当成额外赠送的等待。若平台更早强制终止,应用设置更长的等待也救不了在途请求;预算需要包含必要的退出阶段和余量。
拿一条时间线检验你的设想
假设零秒收到停机通知,一秒时不再接受新业务,原有请求甲在四秒完成,请求乙要到四十秒才完成,而平台在三十秒期限后可能强制结束。甲有机会正常返回;乙不能仅凭“开启优雅停机”就保证完成。这个时间线是设计练习,没有运行真实集群。
乙若已经提交数据库而响应没送达,客户端仍可能面对结果未知。停机策略需要和幂等重试、结果查询相配合。把请求从 HTTP 线程转交后台线程,也不等于它已经可靠保存;进程退出时,只有内存里的任务仍可能消失,必须明确任务归属和持久化时机。
用三类请求观察停机
在自己的测试环境准备短请求、可控慢请求和超时请求,开始停机后检查新请求是否停止接纳、已有请求是否完成、超时任务有没有清楚的结果。测试应使用平台真实的终止方式;某些 IDE 的停止按钮可能立即终止进程,和正常关闭流程不同。
记录接纳时间、业务提交时间、响应完成时间与进程退出时间,再对照客户端看到的结果。后台消费者、定时任务和自建线程池也要有各自的停止规则,不能把 Web 服务器收尾等同于整个应用所有工作均已完成。最后验证超时后的恢复过程,才知道剩余工作会被谁接手。
记住这三点
- 优雅停机要同时处理新请求、在途请求和退出期限。
- 应用阶段超时与平台终止期限需要协调,
preStop也占时间。 - 提交完成但响应丢失仍需幂等与查询机制处理。
别把例子用过头
- 假设时间线不是集群实测,具体服务器和代理行为需要验证。
- Web 请求排空不能代表所有后台任务已收尾。
- 强制终止、机器故障等情况不保证执行普通关闭钩子。
自己试一小步
一个可能运行五分钟的导出任务,如何避免把每次发布都拖五分钟?
- 区分请求接纳、任务持久化、任务执行和结果领取四个时刻。
- 列出停机发生在各时刻时,用户能查询到的状态。
- 提出恢复或重新领取任务的规则,并说明怎样防止重复产物。
做到这些,就算完成
- 没有把后台线程等同于持久队列。
- 退出有明确的最长等待预算。
- 考虑到数据库提交后响应丢失的情况。
查原始资料
想确认一个细节,先看这份资料对应的部分,不必从头读完所有文档。
- Spring Boot 3.5: Graceful Shutdown (新标签页)↗
支持关闭阶段超时、已有请求完成、服务器拒绝方式差异和 IDE 终止信号提示。
- Pod 的生命周期 (新标签页)↗
直接阅读 Pod 终止流程:
preStop、TERM、终止端点状态以及期限后强制结束。
找一份资料继续练
先选一项,按下面的范围继续学;不必从头读完整门课程。
Spring Boot:先停接新请求,再完成手头工作 (新标签页)↗
只读平稳停机与生命周期表,标出新请求、旧请求和等待期限,按项目版本核对行为。
查看学习准备与访问说明 →