Springboot-优雅停机,外部Tomcat

由于springboot自带的停止服务/actuator/shutdown,版本/集成其他插件冲突等种,种原因导致直接抛异常结束。无法满足需求。 

@Slf4j
@Component
public class GracefulTomcatTest implements ApplicationListener {
    @Autowired
    private ApplicationInfoManager applicationInfoManager;
    @Override
    public void onApplicationEvent(ContextClosedEvent contextClosedEvent) {
        try {
            //TODO 拉出服务,不再接收请求 Health.Builder().down().build()
            log.info("从注册中心拉出微服务---,{}", contextClosedEvent.getTimestamp());
            applicationInfoManager.getInfo().setStatus(InstanceInfo.InstanceStatus.DOWN);
        }catch (Exception e){
            log.info("拉出异常{}",e);
        }finally {
            try {
                log.info("暂停30秒-等待未处理完成的线程--,{}", contextClosedEvent.getTimestamp());
                TimeUnit.SECONDS.sleep(30);
                log.info("暂停30秒结束---,{}", contextClosedEvent.getTimestamp());
            } catch (InterruptedException e) {
                log.info("异常{}",e);
            }
        }

    }
}

kill -15  [pid]  进行验证

验证结果:

   1 一个请求耗时20秒,请求进入后,执行 kill -15命令,这个请求会正常执行结束。

    2 一个请求耗时40秒,请求进入后,立即执行 kill -15命令,这个请求不会执行完成。(有好的方案再补充)

Spring内置事件

1、ContextRefreshedEvent

ApplicationContext 被初始化或刷新时,该事件被发布。这也可以在 ConfigurableApplicationContext接口中使用 refresh() 方法来发生。此处的初始化是指:所有的Bean被成功装载,后处理Bean被检测并激活,所有Singleton Bean 被预实例化,ApplicationContext容器已就绪可用

2、ContextStartedEvent

当使用 ConfigurableApplicationContext (ApplicationContext子接口)接口中的 start() 方法启动 ApplicationContext 时,该事件被发布。你可以调查你的数据库,或者你可以在接受到这个事件后重启任何停止的应用程序

3、ContextStoppedEvent

当使用 ConfigurableApplicationContext 接口中的 stop() 停止 ApplicationContext 时,发布这个事件。你可以在接受到这个事件后做必要的清理的工作

4、ContextClosedEvent

当使用 ConfigurableApplicationContext 接口中的 close() 方法关闭 ApplicationContext 时,该事件被发布。一个已关闭的上下文到达生命周期末端;它不能被刷新或重启

5、RequestHandledEvent

这是一个 web-specific 事件,告诉所有 bean HTTP 请求已经被服务。只能应用于使用DispatcherServlet的Web应用。在使用Spring作为前端的MVC控制器时,当Spring处理用户请求结束后,系统会自动触发该事件

拓展阅读:springboot开源方案讨论  issues

服务治理 与 无服务无损下线/重启的实战方案

注册中心用的Eureka

重启或停止按钮,先调用eureka-service 拉出服务 ,再暂停7s,执行shudown停止应用

5秒内eureka-client的缓存会更新,DiscoveryClient会将失效的ip剔除。

eureka-service配置

## 心跳间隔,5秒
eureka.instance.leaseRenewalIntervalInSeconds = 5
## 没有心跳的淘汰时间,10秒
eureka.instance.leaseExpirationDurationInSeconds = 10

## 禁用readOnlyCacheMap 或者缩短更新时间,默认30秒
eureka.server. useReadOnlyResponseCache = false

## readOnlyCacheMap 缩短缓存更新时间
eureka.server.response-cache-update-interval-ms = 20000

client配置

# 定义从注册中心获取注册服务的信息
eureka.client.registry-fetch-interval-seconds = 5
#心跳间隔,5秒
eureka.instance.lease-renewal-interval-in-seconds = 5
#没有心跳的淘汰时间,10秒
eureka.instance.lease-expiration-duration-in-seconds = 10

你可能感兴趣的:(优雅停机,spring,springboot,优雅停机)