首页 > 编程 > Java > 正文

spring boot2.0实现优雅停机的方法

2019-11-26 10:02:15
字体:
来源:转载
供稿:网友

前期踩的坑 (spring boot 1.x)

1. 添加mavne依赖

<!-- springboot监控 --> <dependency>   <groupId>org.springframework.boot</groupId>   <artifactId>spring-boot-starter-actuator</artifactId> </dependency> 

2. 启用shutdown

在配置文件里添加下面的配置

#启用shutdown endpoint的HTTP访问endpoints.shutdown.enabled=true#不需要验证 endpoints.shutdown.sensitive=false

启动的时候可以看到下面的日志,就说明成功了

3. 优雅停机

发送POST请求 http://localhost:8080/shutdown
如果响应码是404 可以尝试POST http://localhost:8080/actuator/shutdown

spring boot 2.0

如果你使用的spring boot版本是2.x的就会发现,这些POST请求都会出现404的结果。

下面是spring boot 2.0 优雅停机的实现方式。

1.修改Application启动类

tomcat容器

@SpringBootApplicationpublic class ShutdownApplication {  public static void main(String[] args) {    SpringApplication.run(ShutdownApplication.class, args);  }  /**   * 用于接受 shutdown 事件   */  @Bean  public GracefulShutdown gracefulShutdown() {    return new GracefulShutdown();  }  /**   * 配置tomcat   *   * @return   */  @Bean  public ServletWebServerFactory servletContainer() {    TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();    tomcat.addConnectorCustomizers(gracefulShutdown());    return tomcat;  }  /**   * 优雅关闭 Spring Boot。容器必须是 tomcat   */  private class GracefulShutdown implements TomcatConnectorCustomizer, ApplicationListener<ContextClosedEvent> {    private final Logger log = LoggerFactory.getLogger(GracefulShutdown.class);    private volatile Connector connector;    private final int waitTime = 10;    @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 进程在" + waitTime + " 秒内无法结束,尝试强制结束");          }        } catch (InterruptedException ex) {          Thread.currentThread().interrupt();        }      }    }  }}

Undertow容器 (没有使用过,不保证可用)

@SpringBootApplicationpublic class Application {  public static void main(String[] args) {    SpringApplication.run(Application.class, args);  }  /**   * 优雅关闭 Spring Boot   */  @Component  public class GracefulShutdown implements ApplicationListener<ContextClosedEvent> {    @Autowired    private GracefulShutdownWrapper gracefulShutdownWrapper;    @Autowired    private ServletWebServerApplicationContext context;    @Override    public void onApplicationEvent(ContextClosedEvent contextClosedEvent){      gracefulShutdownWrapper.getGracefulShutdownHandler().shutdown();      try {        UndertowServletWebServer webServer = (UndertowServletWebServer)context.getWebServer();        Field field = webServer.getClass().getDeclaredField("undertow");        field.setAccessible(true);        Undertow undertow = (Undertow) field.get(webServer);        List<Undertow.ListenerInfo> listenerInfo = undertow.getListenerInfo();        Undertow.ListenerInfo listener = listenerInfo.get(0);        ConnectorStatistics connectorStatistics = listener.getConnectorStatistics();        while (connectorStatistics.getActiveConnections() > 0){}      }catch (Exception e){        // Application Shutdown      }    }  }  @Component  public class GracefulShutdownWrapper implements HandlerWrapper{    private GracefulShutdownHandler gracefulShutdownHandler;    @Override    public HttpHandler wrap(HttpHandler handler) {      if(gracefulShutdownHandler == null) {        this.gracefulShutdownHandler = new GracefulShutdownHandler(handler);      }      return gracefulShutdownHandler;    }    public GracefulShutdownHandler getGracefulShutdownHandler() {      return gracefulShutdownHandler;    }  }  @Component  @AllArgsConstructor  public class UndertowExtraConfiguration {    private final GracefulShutdownWrapper gracefulShutdownWrapper;    @Bean    public UndertowServletWebServerFactory servletWebServerFactory() {      UndertowServletWebServerFactory factory = new UndertowServletWebServerFactory();      factory.addDeploymentInfoCustomizers(deploymentInfo -> deploymentInfo.addOuterHandlerChainWrapper(gracefulShutdownWrapper));      factory.addBuilderCustomizers(builder -> builder.setServerOption(UndertowOptions.ENABLE_STATISTICS, true));      return factory;    }  }}

2. 使用 kill命令杀死进程

使用下面的命令杀死进程。该命令是向 某个进程发送终止信号。

kill -15 [PID]

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持武林网。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表