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

原文地址:https://www.cnblogs.com/liangzs/p/8952378.html