共计 3243 个字符,预计需要花费 9 分钟才能阅读完成。
最近,公司我的项目优化重构,为了我的项目能够无缝高低线,如丝般顺滑,思考到增加优雅停机性能。优雅停机蕴含线程池、音讯、数据库、服务下线。
jvm 有钩子函数在收到 kill 命令后会执行回掉,能够应用这个实现优雅下线。简略介绍一下 kill 命令。- 2 相似于 ctrl+c,kill -15 服务失常下线会触发 jvm 钩子函数。kill - 9 零碎内核间接杀死,不会触发钩子函数。
优雅下线波及到 bean 的生命周期销毁。ContextClosedEvent 和 @PreDestroy 和周期和 DisposableBean 参考链接
https://blog.csdn.net/qq_4384…
线程池、mq、db 等都在 spring 的 bean 销毁之前下线, 留神下线程序。例子:
private ThreadPoolExecutor executor;
@Bean
@Primary
public ThreadPoolExecutor asyncServiceExecutor() {executor = new ThreadPoolExecutor(5, 20, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1000), new ThreadPoolExecutor.CallerRunsPolicy());
return executor;
}
@PreDestroy
public void destroyThreadPool() {if (!executor.isTerminated()){executor.shutdown();
try {executor.awaitTermination(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {e.printStackTrace();
executor.shutdownNow();}
}
log.info("ThreadPoolExecutor destroyed !");
}
dubbo 下线
dubbo 默认开启了优雅停机。下线分为从注册核心下线,敞开协定
2.7 之后源码如下:ShutdownHookListener,继承 Spring ApplicationListener 接口,用以监听 Spring 相干事件。这里 ShutdownHookListener 仅仅监听 Spring 敞开事件,当 Spring 开始敞开,将会触发 ShutdownHookListener 外部逻辑
public class SpringExtensionFactory implements ExtensionFactory {private static final Logger logger = LoggerFactory.getLogger(SpringExtensionFactory.class);
private static final Set<ApplicationContext> CONTEXTS = new ConcurrentHashSet<ApplicationContext>();
private static final ApplicationListener SHUTDOWN_HOOK_LISTENER = new ShutdownHookListener();
public static void addApplicationContext(ApplicationContext context) {CONTEXTS.add(context);
if (context instanceof ConfigurableApplicationContext) {
// 注册 ShutdownHook
((ConfigurableApplicationContext) context).registerShutdownHook();
// 勾销 AbstractConfig 注册的 ShutdownHook 事件
DubboShutdownHook.getDubboShutdownHook().unregister();
}
BeanFactoryUtils.addApplicationListener(context, SHUTDOWN_HOOK_LISTENER);
}
// 继承 ApplicationListener,这个监听器将会监听容器敞开事件
private static class ShutdownHookListener implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationEvent event) {if (event instanceof ContextClosedEvent) {DubboShutdownHook shutdownHook = DubboShutdownHook.getDubboShutdownHook();
shutdownHook.doDestroy();}
}
}
}
通过配置 dubbo.application.shutwait=30s 能够设置 dubbo 等待时间
springboot 下线
相熟介绍 springboot 优雅停机,在 Springboot2.3 之前须要本人实现优雅停机。2.3 后本人实现了优雅停机。
springboot2.3 之前的实现形式。
1、创立 SafetyShutDownConfig 类实现 TomcatConnectorCustomizer,ApplicationListener<ContextClosedEvent> 接口即可,kill - 2 和 kill -15 就能够进行测试
@Slf4j
@Configuration
public class SafetyShutDownConfig implements TomcatConnectorCustomizer, ApplicationListener<ContextClosedEvent> {
private volatile Connector connector;
private final int waitTime = 30;
@Override
public void customize(Connector connector) {this.connector = connector;}
@Override
public void onApplicationEvent(ContextClosedEvent contextClosedEvent) {this.connector.pause();
Executor executor = this.connector.getProtocolHandler().getExecutor();
if (executor instanceof ThreadPoolExecutor) {
try {ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executor;
threadPoolExecutor.shutdown();
if (!threadPoolExecutor.awaitTermination(waitTime, TimeUnit.SECONDS)) {log.warn("Tomcat thread pool did not shut down gracefully within" + waitTime + "seconds. Proceeding with forceful shutdown");
}
} catch (InterruptedException ex) {Thread.currentThread().interrupt();}
}
}
}
springboot2.3 之后的实现
1、在配置文件中开启就能够
#开启优雅停机
server.shutdown=graceful
#优雅停机最大等待时间
spring.lifecycle.timeout-per-shutdown-phase=30s