发布时为什么还会有 502?server.shutdown=graceful 到底保护了什么?preStop 睡几秒才够?阶段超时是多少?这篇用 SIGTERM 加一个会慢的接口,再用 Python 模拟负载均衡的摘除延迟,逐项实测。
什么都不设(默认值)
正在处理的 /slow?ms=3000(SIGTERM 前 0.5 秒发出):200 done after 3000 ms;客户端等了 3.0 秒
SIGTERM 之后 0.3 秒:新建连接请求 /fast → ConnectionRefusedError: [Errno 61] Connection refused;已有的 keep-alive 连接再请求 /fast → RemoteDisconnected: Remote end closed connection without response
进程在 SIGTERM 之后 2.6 秒退出,退出码 143
日志:Commencing graceful shutdown. Waiting for active requests to complete
日志:Graceful shutdown complete
AvailabilityChangeEvent CORRECT
AvailabilityChangeEvent ACCEPTING_TRAFFIC
AvailabilityChangeEvent REFUSING_TRAFFIC
ContextClosedEvent 到达,readiness=REFUSING_TRAFFIC
@PreDestroy 执行
server.shutdown=immediate
正在处理的 /slow?ms=3000(SIGTERM 前 0.5 秒发出):RemoteDisconnected: Remote end closed connection without response;客户端等了 0.5 秒
SIGTERM 之后 0.3 秒:新建连接请求 /fast → ConnectionRefusedError: [Errno 61] Connection refused;已有的 keep-alive 连接再请求 /fast → RemoteDisconnected: Remote end closed connection without response
进程在 SIGTERM 之后 0.3 秒退出,退出码 143
AvailabilityChangeEvent CORRECT
AvailabilityChangeEvent ACCEPTING_TRAFFIC
AvailabilityChangeEvent REFUSING_TRAFFIC
ContextClosedEvent 到达,readiness=REFUSING_TRAFFIC
@PreDestroy 执行
server.shutdown=graceful(阶段超时默认 30 秒)
正在处理的 /slow?ms=3000(SIGTERM 前 0.5 秒发出):200 done after 3000 ms;客户端等了 3.0 秒
SIGTERM 之后 0.3 秒:新建连接请求 /fast → ConnectionRefusedError: [Errno 61] Connection refused;已有的 keep-alive 连接再请求 /fast → RemoteDisconnected: Remote end closed connection without response
进程在 SIGTERM 之后 2.5 秒退出,退出码 143
日志:Commencing graceful shutdown. Waiting for active requests to complete
日志:Graceful shutdown complete
AvailabilityChangeEvent CORRECT
AvailabilityChangeEvent ACCEPTING_TRAFFIC
AvailabilityChangeEvent REFUSING_TRAFFIC
ContextClosedEvent 到达,readiness=REFUSING_TRAFFIC
@PreDestroy 执行
server.shutdown=graceful + spring.lifecycle.timeout-per-shutdown-phase=1s(比请求短)
正在处理的 /slow?ms=3000(SIGTERM 前 0.5 秒发出):RemoteDisconnected: Remote end closed connection without response;客户端等了 1.5 秒
SIGTERM 之后 0.3 秒:新建连接请求 /fast → ConnectionRefusedError: [Errno 61] Connection refused;已有的 keep-alive 连接再请求 /fast → RemoteDisconnected: Remote end closed connection without response
进程在 SIGTERM 之后 1.1 秒退出,退出码 143
日志:Commencing graceful shutdown. Waiting for active requests to complete
日志:Graceful shutdown aborted with one or more requests still active
AvailabilityChangeEvent CORRECT
AvailabilityChangeEvent ACCEPTING_TRAFFIC
AvailabilityChangeEvent REFUSING_TRAFFIC
ContextClosedEvent 到达,readiness=REFUSING_TRAFFIC
@PreDestroy 执行graceful 是默认值;在途请求完成,新连接立刻被拒绝;immediate 会断开在途请求;阶段超时比请求短也会断开。
immediate,不睡(preStop 睡 0 秒)
摘除前共发出 149 个请求,成功 0 个,失败 149 个(ConnectionResetError × 1、ConnectionRefusedError × 148);摘除前 0.1 秒发出的 3 秒请求 → ConnectionRefusedError: [Errno 61] Connection refused
graceful,不睡
摘除前共发出 162 个请求,成功 0 个,失败 162 个(ConnectionResetError × 1、ConnectionRefusedError × 161);摘除前 0.1 秒发出的 3 秒请求 → ConnectionRefusedError: [Errno 61] Connection refused
什么都不设(默认值),不睡
摘除前共发出 157 个请求,成功 0 个,失败 157 个(ConnectionResetError × 1、ConnectionRefusedError × 156);摘除前 0.1 秒发出的 3 秒请求 → ConnectionRefusedError: [Errno 61] Connection refused
immediate,preStop 睡 3 秒
摘除前共发出 122 个请求,成功 122 个,失败 0 个;摘除前 0.1 秒发出的 3 秒请求 → RemoteDisconnected: Remote end closed connection without response
graceful,preStop 睡 3 秒
摘除前共发出 124 个请求,成功 124 个,失败 0 个;摘除前 0.1 秒发出的 3 秒请求 → 200 done after 3000 msgraceful 只保护已经进来的请求;负载均衡还在转发时,新请求会撞上已关闭的端口;preStop 要睡得比摘除传播时间长。
server.shutdown=graceful,没有设置 spring.lifecycle.timeout-per-shutdown-phase
正在处理的 /slow?ms=40000(SIGTERM 前 0.5 秒发出):TimeoutError: timed out;客户端等了 20.0 秒
SIGTERM 之后 0.3 秒:新建连接请求 /fast → ConnectionRefusedError: [Errno 61] Connection refused;已有的 keep-alive 连接再请求 /fast → RemoteDisconnected: Remote end closed connection without response
进程在 SIGTERM 之后 30.1 秒退出,退出码 143
日志:Commencing graceful shutdown. Waiting for active requests to complete
日志:Graceful shutdown aborted with one or more requests still active
AvailabilityChangeEvent CORRECT
AvailabilityChangeEvent ACCEPTING_TRAFFIC
AvailabilityChangeEvent REFUSING_TRAFFIC
ContextClosedEvent 到达,readiness=REFUSING_TRAFFIC
@PreDestroy 执行默认最长等 30 秒,之后日志 aborted 并断开请求。