Spring cloud系列20 实现服务优雅上下线
在使用Spring Cloud微服务的过程中,必然会碰到微服务因为版本升级而重启。如果只是使用kill命令结束服务进程,则依赖此服务的客户端服务不会立即知道目标服务已经下线,仍然会调用目标服务借口,会因为访问失败会抛出异常,为了避免这个情况,我们希望实现服务升级对用户是无感知的
如何解决问题 首先我们搜索网络,发现这篇文章,但是这篇文章的方法都符合我们的业务要求。
后来经过研究发现以下方法,使用EurekaAutoServiceRegistration对象可以达到我们的目的。我们使用的注册中心框架是Eureka
-
执行eurekaAutoServiceRegistration.stop() 方法时,本服务会向Eureka注册中心进行反注册,注册中心收到请求后,会将此服务从注册列表中删除。 执行eurekaAutoServiceRegistration.start() 方法时,本服务向Eureka注册中心注册服务
代码如下:
@RestController @RequestMapping(value = "/test-service") @EnableSwagger2 @Deprecated public class Test { @Autowired private EurekaAutoServiceRegistration eurekaAutoServiceRegistration; @RequestMapping("/online") public String online() { this.eurekaAutoServiceRegistration.start(); return "user online method"; } @RequestMapping("/offline") public String offline() { this.eurekaAutoServiceRegistration.stop(); return "user offline method"; } }
服务启动后,调用以下命令使目标服务下线 http://127.0.0.1:10803/demo//eureka-service/online 登录注册中心看,目标服务已经下线 此时,还不能停止目标服务,因为Eureka实现AP关系,此时依赖目标服务的服务还不知道此服务已经下线,目标服务仍然需要正常运行。等待Ns后,其他服务知道目标服务已经下线,不在访问目标服务,则停止目标服务,然后升级服务
服务调用者多久知道目标服务已经下线 实际应用时,这里有个问题,服务调用者多久知道目标服务已经下线? 我们整理服务整个流程:
- 准备下线服务调用eurekaAutoServiceRegistration.stop()方法
- Eureka注册中心收到注销请求后,会先将信息更新到读写缓存中。Eureka注册中心有两个缓存:读写缓存和只读缓存。关于Eureka注册中对缓存的描述详细见这篇文章
- 注册中心有个定时任务会定时(默认值是30s)将读写缓存中的数据同步到只读缓存中
- 服务调用者务会定时(默认值也是30s)从注册中心拉取次服务列表(为了提高性能,此时只是从只读缓存中获取),并更新本地信息
综上,服务调用者最多花费60s(30s+30s)就可以知道服务已经下线