关于SpringCloud基于Rancher的优雅停服
1、通过jenkins的kubctl向Rancher发布镜像时。第一步在Rancher容器内设置健康检查。通过K8S健康检查,以双服务node为例:能达到先启动一个新服务,再停掉第一个旧服务;然后会自动启动第二个新服务,再停掉一个旧服务。具体健康检查如下:2、设置健康检查以后,我们再发版过程中,通过jmeter实时对服务进行测试,发现有失败的服务。其中有一些服务报timeout。我们想到ribbo
1、通过jenkins的kubctl向Rancher发布镜像时。第一步在Rancher容器内设置健康检查。通过K8S健康检查,以双服务node为例:能达到先启动一个新服务,再停掉第一个旧服务;然后会自动启动第二个新服务,再停掉一个旧服务。
具体健康检查如下:
2、设置健康检查以后,我们再发版过程中,通过jmeter实时对服务进行测试,发现有失败的服务。其中有一些服务报timeout。我们想到ribbon的重试机制。但是发现timeout在单服务超时时间内就直接报错了。由此推测重试没生效。
经过修改gateway的配置文件:retryable要设置为true, MaxAutoRetriesNextServer为重试次数。
zuul:
retryable: true
ribbon-isolation-strategy: thread
thread-pool:
use-separate-thread-pools: true
ribbon:
okhttp:
enabled: true
MaxTotalConnections: 500
MaxConnectionsPerHost: 2000
#Http请求中的socketTimeout
ReadTimeout: 3000
#Http请求中的connectTimeout
ConnectTimeout: 3000
# 切换实例的重试次数
MaxAutoRetriesNextServer: 1
# 对当前实例的重试次数
MaxAutoRetries: 0
同时,gateway代码中要引入包:
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
3、经过设置ribbon重试。发现没有再出现timeout的错误。但是依然在版本切换中有一些服务在70~80ms就报错。报错体现微服务的代码层面。我们怀疑是注册中心没有实时刷新的原因。于是我们在k8s的钩子prestop中主动调微服务api,向registry发起服务下线的请求。
4、服务在强停止之前,会先向注册中心发起下线请求。然后让服务在停服之前先sleep 10秒。通过测试发现,服务下线前,注册中心确实down了对应的微服务,但是jmeter测试仍然有报错。我们猜想registry可能有缓存。
5、于是我们禁用了registry的缓存。
6、同时,我们调整了gateway拉取registry路由列表的时长为5s,默认是30s。
7、此刻再用jmeter调用。发现不再出现服务失败的情况。且能实现优雅停服发版。
8、为什么仍然会有偶发的调用失败?
首先,k8s停node时,由于微服务上报心跳时间是5s,虽然registry设置了过期时间是5s,但是cache的存在,导致注册中心并没有实时刷新。依然有新的请求调动过来。
9、为什么要主动上报registry?
如果不在k8s中实时的curl api通知registry下线服务。在k8s sleep的10秒钟内,微服务心跳每5秒自动上报的状态仍然是up。
10、那为什么k8s通知了registry下线服务后仍然要sleep 10秒呢?
(1)我们要给gateway拉取registry的间隔5秒留时间。(注意:gateway默认不是5秒)
(3)如果刚好4.99秒时,有请求过来,gateway没刷新,依然调用到了旧微服务上,此时需要给该请求在旧服务上留有执行时间。我们的单请求的执行时间都在毫秒级,只要大于5秒,时间依情况而定。
更多推荐
所有评论(0)