本文章介绍了正常关闭Spring Boot 应用程序的过程。许多开发人员和架构师总是讨论SpringBoot的应用设计、流量负载、框架和应用模式,但很少有人讨论关闭阶段。生命周期意识可以说一个真正资深程序员应该具有的素质,对于重资源对象,包括线程池 连接池等都要有始有终,不能只顾创建。

对于 SpringBoot 来说,打包成一个简单的 Jar 包直接使用 java -jar即可启动,这是一种非常优雅的方式,但同时也带来了一定的问题,如:应用如何停止?在过去,应用程序是部署在特定的容器中的,使用容器提供的脚本可以优雅停服,但现在容器被内嵌了,脚本没有了,怎么办?直接 kill 是一种方式,但未免显得太过粗鲁,而且可能带来许多意想不到的问题。


下面记录一种方案。

使用 Endpoints

在 SpringBoot 官方文档的第5部分中介绍了为应用发布生产准备的各种特性,其中,通过 Actuator 的 HTTP Endpoint,开发人员可以方便地对应用的监控与管理。此方法配合winsw使用,适用于window服务器,有需要请参考:在windows服务器上使用winsw部署spring boot项目

引入指定的SpringBoot starter包

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

在 application.properties 中打开如下两个配置,即可实现通过 Http 请求停止应用

management.endpoints.web.exposure.include=*
management.endpoint.shutdown.enabled=true

操作命令如下:

curl -X POST http://host:port/actuator/shutdown

但这种方式有一个非常严重的问题,那就是任意人都可以控制应用的停止,为了保证系统的安全,需要给其加上一层 HTTP Basic Auth

增加 Security 依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

在 application.properties 中增加如下两个配置:

spring.security.user.name=actuator
spring.security.user.password=password
spring.security.user.roles=ACTUATOR

增加security过滤规则

@Configuration
public class ActuatorWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.csrf().disable().authorizeRequests().antMatchers("/").permitAll()
		.requestMatchers(EndpointRequest.toAnyEndpoint()).hasRole("ACTUATOR")
        .anyRequest().authenticated().and()
        //开启basic认证,若不添加此项,将不能通过curl的basic方式传递用户信息
        .httpBasic();
	}

}

配置完成后,最终的停服命令为:

curl -X POST -u actuator:password http://host:port/actuator/shutdown

执行返回:{"message":"Shutting down, bye..."},说明服务停止成功。

02-18 23:05