bigywater.tech
Spring · 134

启动顺序:注册、健康检查与流量进入

服务注册到注册中心的时候已经能接流量了吗?readiness 探针和注册中心什么关系?怎么让预热完成之后才注册?这篇用真实的 Nacos、一个有 3 秒预热的服务和每 20 毫秒调一次的调用方量出来,并如实记录几条没走通的路。

121 次
预热 3 秒期间,调用方在实例注册之后收到的 503 次数
0 次
预热放进 SmartLifecycle(phase 0)后,调用方的 503 次数
3 条没走通
register-enabled=false 手工注册、auto-registration.enabled=false、instance-enabled=false 加 setStatus

默认时间线

实测 · 本机执行输出
  [默认] 以 Tomcat 开始接受连接为 0:实例出现在 Nacos 0.4 秒;/hello 第一次 200 3.4 秒;/actuator/health/readiness 变 200 3.5 秒;ApplicationReadyEvent 3.4 秒
    调用方在实例出现在 Nacos 之后每 20 ms 调一次 /hello:成功 81 次,失败(503)121 次

注册在 Web 服务器启动时,readiness 在 ReadyEvent 之后,注册中心不看 readiness。

手工注册

实测 · 本机执行输出
  [register-enabled=false + 手工注册] 以 Tomcat 开始接受连接为 0:/hello 第一次 200 3.1 秒;/actuator/health/readiness 变 200 3.4 秒;实例出现在 Nacos None 秒;ApplicationReadyEvent 3.0 秒
    调用方在实例出现在 Nacos 之后每 20 ms 调一次 /hello:成功 0 次,失败(503)0 次
    应用日志里的相关行:手工调用 NacosServiceRegistry.register(...) | register 抛出 UndeclaredThrowableException: null

register 抛 UndeclaredThrowableException。

关闭自动注册

实测 · 本机执行输出
  [auto-registration.enabled=false + 手工注册] 以 Tomcat 开始接受连接为 0:/actuator/health/readiness 变 200 3.1 秒;/hello 第一次 200 3.1 秒;实例出现在 Nacos None 秒;ApplicationReadyEvent 3.0 秒
    调用方在实例出现在 Nacos 之后每 20 ms 调一次 /hello:成功 0 次,失败(503)0 次
    应用日志里的相关行:手工注册失败:registry=null,registration=null

相关 bean 都没了。

instance-enabled

实测 · 本机执行输出
  [instance-enabled=false + 就绪后 setStatus UP] 以 Tomcat 开始接受连接为 0:/actuator/health/readiness 变 200 3.3 秒;/hello 第一次 200 3.3 秒;实例出现在 Nacos None 秒;ApplicationReadyEvent 3.3 秒
    调用方在实例出现在 Nacos 之后每 20 ms 调一次 /hello:成功 0 次,失败(503)0 次
    应用日志里的相关行:调用 NacosServiceRegistry.setStatus(registration, UP) | setStatus 返回

setStatus 之后实例仍不可见,没走通。

SmartLifecycle

实测 · 本机执行输出
  [预热在 SmartLifecycle 里] 以 Tomcat 开始接受连接为 0:/hello 第一次 200 0.1 秒;/actuator/health/readiness 变 200 0.4 秒;实例出现在 Nacos 0.9 秒;ApplicationReadyEvent 0.3 秒
    调用方在实例出现在 Nacos 之后每 20 ms 调一次 /hello:成功 152 次,失败(503)0 次
    应用日志里的相关行:SmartLifecycle(phase 0)开始预热 3 秒 @0.0s | SmartLifecycle 预热完成 @3.0s | Web 服务器启动(WebServerInitializedEvent) @3.3s | ApplicationRunner:预热已经在 SmartLifecycle 里做完,这里什么都不做 @3.4s | ApplicationReadyEvent @3.4s

预热放在 Web 服务器启动之前,注册自然延后。

分步演示

启动顺序
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / OpenJDK 21.0.12(Homebrew) / Spring Boot 4.0.8(Spring Framework 7.0.9、Tomcat 11.0.24) / Spring Cloud 2025.1.3;用 javac 编译、java 直接运行,依赖由 Maven 从 Maven Central 解析;数字每次运行会有小幅抖动。Nacos Server 3.1.1 单机模式(自己起的);时间是 Python 在宿主机上每 20 ms 轮询得到的,有几十毫秒误差;预热用 Thread.sleep(3000) 模拟;「调用方」是 Python 线程,发现实例后每 20 ms 直接调一次应用的 /hello(没有经过 LoadBalancer)
    • 没有验证:第 2、4 步失败的具体原因(我只记录了现象);Kubernetes 里 readinessProbe 控制 Service 流量的行为(第 133 篇有集群,这里没有部署 Pod);Eureka / Consul 的注册时机;Nacos 3 客户端是否有「延迟注册」的原生配置;预热期间 Tomcat 没启动对探针与负载均衡健康检查的影响;优雅停机时的反向顺序(第 117 篇)
    京ICP备2026067502号-1京公网安备11010502063487号