Spring boot 2.3优雅下线,距离生产还有多远?( 二 )


2、public TomcatWebServer(Tomcat tomcat, boolean autoStart, Shutdown shutdown) {3、 Assert.notNull(tomcat, ''Tomcat Server must not be null'');4、 this.tomcat = tomcat;5、 this.autoStart = autoStart;6、 this.gracefulShutdown = (shutdown == Shutdown.GRACEFUL) ? new GracefulShutdown(tomcat) : null;7、 initialize();8、}
可以看到当我们配置 server.shutdown=graceful 时 , 其中 gracefulShutdown 成员就不为null , 而是被置为 GracefulShutdown 实例 。 当我们关闭SpringBoot的应用容器时 , 会触发其生命周期的 stop 方法 , 我们看到其中会执行webServer的shutDownGracefully方法
Spring boot 2.3优雅下线,距离生产还有多远?
本文插图
因为我们配置 了server.shutdown=graceful, 所以 gracefulShutdown 成员并不为null , 而是会触发 gracefulShutdown 的 shutDownGracefully 方法
Spring boot 2.3优雅下线,距离生产还有多远?
本文插图
我们看一下shutDownGracefully 方法是如何做到graceful shutdown的
Spring boot 2.3优雅下线,距离生产还有多远?
本文插图
来看一下doShutdown的逻辑org.springframework.boot.web.embedded.tomcat.GracefulShutdown#doShutdownprivate void doShutdown(GracefulShutdownCallback callback) {
List connectors = getConnectors(); connectors.forEach(this::close); try { for (Container host : this.tomcat.getEngine().findChildren()) { for (Container context : host.findChildren()) { while (isActive(context)) { if (this.aborted) { logger.info(''Graceful shutdown aborted with one or more requests still active''); callback.shutdownComplete(GracefulShutdownResult.REQUESTS_ACTIVE); return; } Thread.sleep(50); } } } } catch (InterruptedException ex) { Thread.currentThread().interrupt(); } logger.info(''Graceful shutdown complete''); callback.shutdownComplete(GracefulShutdownResult.IDLE);}
先是关闭掉所有的连接 , 在网络层停止接受请求 , 然后再等待所有请求处理完毕 。 其中关于 spring.lifecycle.timeout-per-shutdown-phase 配置 , 是通过等待配置的时间后 , 再执行TomcatWebServer的stop方法 , 将其aborted成员置为true , 实现如果应用在宽限期之后仍然有待处理的请求 , 应用程序将抛出异常并继续强制关闭 , 而不是一直等待下去 。 @Overridepublic void stop() throws WebServerException {
this.aborted = true;}
void abort() {
this.aborted = true;}
在微服务场景下问题似乎依旧存在...总结一下一个 Spring Cloud 应用正常分批发布的流程1、服务发布前 , 消费者根据负载均衡规则调用服务提供者 , 业务正常 。 2、服务提供者 B 需要发布新版本 , 先对其中的一个节点进行操作 , 先是正常停止 Java 进程 。 3、服务停止过程中 , 首先去注册中心注销服务 , 然后等待服务端线程处理完成 , 再停止服务 。 4、注册中心则将通知消费者 , 其中的一个服务提供者节点已下线 。 这个过程包含推送和轮询两种方式 , 推送可以认为是准实时的 , 轮询的耗时由服务消费者轮询间隔决定 , 最差的情况下需要 1 分钟 。 5、服务消费者刷新服务列表 , 感知到服务提供者已经下线了一个节点 , 但是这个过程中Spring Cloud 的负载均衡组件 Ribbon 默认的刷新时间是 30 秒, 最差情况下需要耗时 30 秒 。 6、服务消费者不再调用已经下线的节点