《​​consul之:常用API接口​​》




之前的方案:先调用待更新的模块的shutdown的Endpoint,这是springboot的功能实现,consul上可见服务确实下线了,再kill掉进程。但是还会有一些请求被转发到该节点上,导致少量的错误。

总结的几种:

1、直接kill方式关闭服务进程

2、向注册中心发送取消注册命令

3、发指令给注册中心,改变指定微服务的服务状态

4、客户端主动通知注册中心下线

5、设置指定模块的服务的状态,可通过状态变更来实现再eureka的上下线

 

1、直接kill方式关闭服务进程

kill -9 没有善后

kill -15  有善后 会发送down状态到eureka server

kill java进程【不建议】

这种方式简单粗暴,直接造成的影响就是部分模块调用时出错,如果有多台服务器的话,一台一台地重启还是可以的,前提是调用端得有自己的重试策略,比如使用Feign作为客户端调用接口的话可以配置ribbon的重试策略,而且被调用方得做好幂等策略,防止重试调用时出现重复数据的问题。


 

2、向注册中心发送取消注册命令

2.1、eureka

向eureka 注册中心发送delete 请求,只是取消注册服务, 当发送心跳时还是会注册到eureka

格式为   eureka地址/eureka/apps/服务名称/实例名称

请求方式为delete

下面是取消注册一个服务的例子。

springCloud+consul优雅停机_springcloud

 

  下图是用postman 发送delete请求

springCloud+consul优雅停机_springcloud_02

 

2.2、consul

PUT 请求

http://10.200.110.100:8500/v1/agent/service/deregister/tag-10-200-110-100-8778


3、发指令给注册中心,改变指定微服务的服务状态

3.1、eureka

通过eureka变更服务状态的方式实现服务上下线,不会再发送心跳注册到eureka server

springCloud+consul优雅停机_微服务_03

 

 3.2、consul

PUT方式: http://10.200.110.100:8500/v1/agent/service/maintenance/tag-10-200-110-100-8778?enable=true&reason=sprint40

执行完成后,consul的控制台如下:

springCloud+consul优雅停机_springcloud_04

观察/tag-10-200-110-100-8778的实时日志,看新请求进来后,再停机

 

4、客户端主动通知注册中心下线

4.1、eureka

客户端主动通知注册中心下线,下线后不会再注册到eureka了

如果你的eureka客户端是是一个spring boot应用,可以通过调用以下代码通知注册中心下线。



import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.netflix.discovery.DiscoveryManager;
import com.shm.common.model.RespVO;
import com.shm.common.util.RespUtil;

@RestController
public class OfflineController {


@RequestMapping(value = "/offline", method = RequestMethod.GET)
public RespVO<Object> offLine(){
DiscoveryManager.getInstance().shutdownComponent();
return RespUtil.success();
}


}


4.2、consul

 

5、设置指定模块的服务的状态,可通过状态变更来实现再eureka的上下线

5.1、eureka

设置服务的状态,可通过状态变更来实现再eureka的上下线

pom中加入

actuator的包



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


以上的方式都能实现服务的下线,但是有的时候只想要下线某个服务,却不需要发布,等待事情处理完成后上线此服务,则以上方式就做不到了。这时可以通过设置微服务的状态来完成此功能。项目中整合了actuator的话就非常简单了,在项目启动的时候可以看到控制台的输出:

springCloud+consul优雅停机_微服务_05

/actuator/service-registry 可以已Get的方式获取当前服务的状态,以Post的方式修改当前服务状态,如将服务设置为Down状态,这样其他微服务接收到此状态后将不调用此服务。将order服务状态设置为Down:

 springCloud+consul优雅停机_微服务_06

看下执行后的效果:

springCloud+consul优雅停机_客户端_07

等到流量都没有进来后,需要发布的话直接发布接口,不需要发布可以直接上线当前服务:

这样一个服务的上线和下线就优雅的完成了,如果项目中没有使用Actuator框架,可以模仿Actuator框架的实现方式,详见类:ServiceRegistryEndpoint

如果要再上线:

springCloud+consul优雅停机_springcloud_08

5.2、consul

shutdown

springboot1.5版本

首先配置:



endpoints.shutdown.enabled: true
#endpoint.shutdown.enabled: true
endpoint.shutdown.sensitive: false
management.endpoints.web.exposure.include: "shutdown"




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


 

6、​​/pause​​端点

Spring Boot 应用提供了​​/pause​​端点,利用该端点可实现优雅下线。

使用方式:在想下线应用的​​application.yml​​中添加配置,从而启用并暴露​​/pause​​端点:



management:
endpoint:
# 启用pause端点
pause:
enabled: true
# 启用restart端点,之所以要启用restart端点,是因为pause端点的启用依赖restart端点的启用
restart:
enabled: true
endpoints:
web:
exposure:
include: pause,restart


发送 POST 请求到/​​actuator/pause​​端点:

  • ​curl -X POST http://你想停止的服务实例地址/actuator/pause​

执行后的效果类似下图:

springCloud+consul优雅停机_springcloud_09

如图所示,该应用在 Eureka Server 上的状已被标记为​​DOWN​​,但是应用本身其实依然是可以正常对外服务的。在 Spring Cloud 中,Ribbon 做负载均衡时,只会负载到标记为​​UP​​的实例上。利用这两点,你可以:先用​​/pause​​端点,将要下线的应用标记为​​DOWN​​,但不去真正停止应用;然后过一定的时间(例如 90 秒,或者自己做个监控,看当前实例的流量变成 0 后)再去停止应用,例如​​kill​​应用。

  • 缺点 & 局限


缺点

描述

不同的版本配置不大一样

早期的 Spring Cloud 版本中,​​pause​​端点是不依赖​​restart​​端点的

无法和 Eureka 的健康检查配合使用

如果你的服务发现组件用的是 Eureka,并且你的应用开启了健康检查​​eureka.client.healthcheck.enabled = true​​,那么​​/pause​​端点无效


 

总结

以上几种方式都可以实现微服的下线,3和5的方式最为优雅,可以主动下线和上线,在没有新流量进来后可以随时发布,这样在也不用等到半夜12点发布了。