ServletWebServerApplicationContext
private void createWebServer() { WebServer webServer = this.webServer; ServletContext servletContext = getServletContext(); if (webServer == null && servletContext == null) { StartupStep createWebServer = this.getApplicationStartup().start("spring.boot.webserver.create"); ServletWebServerFactory factory = getWebServerFactory(); createWebServer.tag("factory", factory.getClass().toString()); this.webServer = factory.getWebServer(getSelfInitializer()); createWebServer.end(); //就是这里,创建一个 WebServerGracefulShutdownLifecycle 并注册到当前 ApplicationContext 的 BeanFactory 中 getBeanFactory().registerSingleton("webServerGracefulShutdown", new WebServerGracefulShutdownLifecycle(this.webServer)); getBeanFactory().registerSingleton("webServerStartStop", new WebServerStartStopLifecycle(this, this.webServer)); } else if (servletContext != null) { try { getSelfInitializer().onStartup(servletContext); } catch (ServletException ex) { throw new ApplicationContextException("Cannot initialize servlet context", ex); } } initPropertySources(); }
前面说到, ApplicationContext 的关闭过程的第三步调用所有 Lifecycle 的 stop 方法,这里即 WebServerGracefulShutdownLifecycle 中的 stop 方法:
WebServerGracefulShutdownLifecycle
@Override public void stop(Runnable callback) { this.running = false; this.webServer.shutDownGracefully((result) -> callback.run()); }
这里的 webServer,由于我们使用的是 Undertow,对应实现就是 UndertowWebServer,看一下他的 shutDownGracefully 实现:
//这里的这个 GracefulShutdownHandler 就是前面说的在启动时加的 GracefulShutdownHandler private volatile GracefulShutdownHandler gracefulShutdown; @Override public void shutDownGracefully(GracefulShutdownCallback callback) { // 如果 GracefulShutdownHandler 不为 null,证明开启了优雅关闭(server.shutdown=graceful) if (this.gracefulShutdown == null) { //为 null,就证明没开启优雅关闭,什么都不等 callback.shutdownComplete(GracefulShutdownResult.IMMEDIATE); return; } //开启优雅关闭,需要等待请求处理完 logger.info("Commencing graceful shutdown. Waiting for active requests to complete"); this.gracefulShutdownCallback.set(callback); //调用 GracefulShutdownHandler 的 shutdown 进行优雅关闭 this.gracefulShutdown.shutdown(); //调用 GracefulShutdownHandler 的 addShutdownListener 添加关闭后调用的操作,这里是调用 notifyGracefulCallback //其实就是调用方法参数的 callback(就是外部的回调) this.gracefulShutdown.addShutdownListener((success) -> notifyGracefulCallback(success)); } private void notifyGracefulCallback(boolean success) { GracefulShutdownCallback callback = this.gracefulShutdownCallback.getAndSet(null); if (callback != null) { if (success) { logger.info("Graceful shutdown complete"); callback.shutdownComplete(GracefulShutdownResult.IDLE); } else { logger.info("Graceful shutdown aborted with one or more requests still active"); callback.shutdownComplete(GracefulShutdownResult.REQUESTS_ACTIVE); } } }
再看下 GracefulShutdownHandler 的 shutdown 方法以及 addShutdownListener 方法:
public void shutdown() { //设置关闭状态位,并原子 + 1 stateUpdater.updateAndGet(this, incrementActiveAndShutdown); //直接请求数原子减一 decrementRequests(); } private void decrementRequests() { long snapshot = stateUpdater.updateAndGet(this, decrementActive); // Shutdown has completed when the activeCount portion is zero, and shutdown is set. //如果与 关闭状态位 MASK 完全相等,证明其他位都是 0,证明剩余处理中的请求数量为 0 if (snapshot == SHUTDOWN_MASK) { //调用 shutdownComplete shutdownComplete(); } } private void shutdownComplete() { synchronized (lock) { lock.notifyAll(); //调用每个 ShutdownListener 的 shutdown 方法 for (ShutdownListener listener : shutdownListeners) { listener.shutdown(true); } shutdownListeners.clear(); } } /** * 这个方法并不只是字面意思,首先如果不是关闭中不能添加 ShutdownListener * 然后如果没有请求了,就直接调用传入的 shutdownListener 的 shutdown 方法 * 如果还有请求,则添加入 shutdownListeners,等其他调用 shutdownComplete 的时候遍历 shutdownListeners 调用 shutdown * lock 主要为了 addShutdownListener 与 shutdownComplete 对 shutdownListeners 的访问安全 * lock 的 wait notify 主要为了实现 awaitShutdown 机制,我们这里没有提 */ public void addShutdownListener(final ShutdownListener shutdownListener) { synchronized (lock) { if (!isShutdown(stateUpdater.get(this))) { throw UndertowMessages.MESSAGES.handlerNotShutdown(); } long count = activeCount(stateUpdater.get(this)); if (count == 0) { shutdownListener.shutdown(true); } else { shutdownListeners.add(shutdownListener); } } }
这就是优雅关闭的底层原理,但是我们还没有分析清楚 ApplicationContext 的关闭过程的第三步以及优雅关闭与其他 Lifecycle Bean 的 stop 先后顺序,我们这里来理清一下,首先我们看一下 Smart
开始关闭 Lifecycle Bean 的入口:
private void stopBeans() { //读取所有的 Lifecycle bean,返回的是一个 LinkedHashMap,遍历它的顺序和放入的顺序一样 //放入的顺序就是从 BeanFactory 读取所有 Lifecycle 的 Bean 的返回顺序,这个和 Bean 加载顺序有关,不太可控,可能这个版本加载顺序升级一个版本就变了 Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans(); //按照每个 Lifecycle 的 Phase 值进行分组 //如果实现了 Phased 接口就通过其 phase 方法返回得出 phase 值 //如果没有实现 Phased 接口则认为 Phase 是 0 Map<Integer, LifecycleGroup> phases = new HashMap<>(); lifecycleBeans.forEach((beanName, bean) -> { int shutdownPhase = getPhase(bean); LifecycleGroup group = phases.get(shutdownPhase); if (group == null) { group = new LifecycleGroup(shutdownPhase, this.timeoutPerShutdownPhase, lifecycleBeans, false); phases.put(shutdownPhase, group); } group.add(beanName, bean); }); //如果不为空,证明有需要关闭的 Lifecycle,开始关闭 if (!phases.isEmpty()) { //按照 Phase 值倒序 List<Integer> keys = new ArrayList<>(phases.keySet()); keys.sort(Collections.reverseOrder()); //挨个关闭 for (Integer key : keys) { phases.get(key).stop(); } } }
总结起来,其实就是:
- 获取当前 ApplicationContext 的 Beanfactory 中的所有实现了 Lifecycle 接口的 Bean。
- 读取每个 Bean 的 Phase 值,如果这个 Bean 实现了 Phased 接口,就取接口方法返回的值,如果没有实现就是 0.
- 按照 Phase 值将 Bean 分组
- 按照 Phase 值从大到小的顺序,依次遍历每组进行关闭
- 具体关闭每组的逻辑我们就不详细看代码了,知道关闭的时候其实还看了当前这个 Lifecycle 的 Bean 是否还依赖了其他的 Lifecycle 的 Bean,如果依赖了,优先关掉被依赖的 Lifecycle Bean
我们来看下前面提到的优雅关闭相关的 WebServerGracefulShutdownLifecycle
的 Phase 是:
class WebServerGracefulShutdownLifecycle implements SmartLifecycle { .... }