spring cloud shutdown graceful 优雅停机
spring cloud shutdown graceful 优雅停机
当一个服务启动后,会注册到eureka中,其他的服务也可以从eureka获取到新注册的服务。但当我们要停止一个服务的时候,如果直接kill -9 pid,未免有些太过暴力。
直接杀进程有什么问题
eureka要经过一段时间才会把已经挂掉的服务踢出,其他的服务上也还会保留住这个服务一段时间,他们都认为该服务可用。eureka的管理界面中还可以看到该服务,其他服务则还保留这个服务副本一段时间。这时候,如果发起一个请求,就会发生错误,服务不存在或降级。
解决办法
spring cloud中,提供了shutdown端点,可以实现优雅停机。eureka可以马上把这个服务剔除,其他的服务中保留的这个服务也将被马上踢出。
pom.xml增加依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
application.properties增加配置
# 启用shutdown
endpoints.shutdown.enabled=true
# 禁用密码验证
endpoints.shutdown.sensitive=false
服务启动后,可以通过linux的curl命令发送POST请求的方式优雅的停止服务。
curl -X POST host:port/shutdown
如果配置了management.context-path=/manage
,则命令变为:
curl -X POST host:port/manage/shutdown
额外的拓展
如果调用了curl -X POST host:port/shutdown
命令后,还想做一些别的操作,可以在主类中增加监听。
代码如下:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.validation.constraints.NotNull;
@SpringBootApplication
@EnableFeignClients
@EnableDiscoveryClient
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@NotNull
@Bean
ServletListenerRegistrationBean<ServletContextListener> myServletListener() {
ServletListenerRegistrationBean<ServletContextListener> srb =
new ServletListenerRegistrationBean<>();
srb.setListener(new ExampleServletContextListener());
return srb;
}
public class ExampleServletContextListener implements ServletContextListener {
@Override
public void contextInitialized(
ServletContextEvent sce) {
// Context Initialised
}
@Override
public void contextDestroyed(
ServletContextEvent sce) {
// Here - what you want to do that context shutdown
System.out.println("==============调用了shutdown后输出==================");
}
}
}
参考:
https://blog.csdn.net/qq276726581/article/details/55520762
https://blog.csdn.net/chinrui/article/details/78685032
https://stackoverflow.com/questions/26678208/spring-boot-shutdown-hook/48181392#48181392