k8s環境下spring cloud優雅停機


目的

 Spring cloud 微服務、k8s容器化部署的架構下,單個服務升級過程中,不停止對外提供服務,使得用戶對整個升級過程無感知,從而實現服務的優雅升級。

負載均衡器

  1. spring cloud ribbon(k8s同namespace):k8s同一命名空間之間的服務調用,采用ribbon、eureka做服務注冊和負載均衡。

     問題:

        a、ribbon和eureka(CP)注重服務的可用性,所以存在服務實例的緩存,本地緩存:(1)ribbon本地緩存 (2)eureka client本地緩存 。遠程緩存:(1)eureka server 三級緩存

        b、service 提供者停止,pod 向容器發送SIGTERM信號,service 提供者會向eureka server下線服務,這個時候service消費者會存在原有service的實例信息

  2. k8s  service (k8s不同namespce):  k8s不同命名空間之間的服務調用,采用k8s service、kube-proxy做服務注冊和負載均衡。

     問題:

       a、k8s service 支持服務的負載均衡,只有容器探針檢測成功后,才會停止舊的容器Service。采用兩種探針實現RollingUpdate。但是前提要存在多個實例

 

基於spring cloud 負載均衡的優雅停機

  針對spring cloud負載均衡存在的問題,要做到優雅停機,需要進行如下配置:

 a、縮短緩存時間

   1. 修改Client配置(ribbon和eureka client)

 1 ribbon:
 2   # ribbon刷新eureka的時間5s, 默認30s
 3   ServerListRefreshInterval: 5000
 4 #注冊中心
 5 eureka:
 6   client:
 7     serviceUrl:
 8       defaultZone: http://eureka-server:8761/eureka
 9     # eureka客戶端需要多長時間發定時刷新本地緩存時間,默認30s
10     registry-fetch-interval-seconds: 5
11   instance:
12     prefer-ip-address: true
13     instance-id: ${spring.cloud.client.ipAddress}:${server.port}
14     # eureka客戶端需要多長時間發送心跳給eureka服務器,表明他仍然活着,默認30秒
15     lease-renewal-interval-in-seconds: 5
16     # eureka服務器在接受到實力的最后一次發出的心跳后,需要等待多久才可以將此實例刪除 默認90秒
17     lease-expiration-duration-in-seconds: 15

    縮短ribbon本地緩存時間,eureka client拉取注冊表、心跳間隔時間 

   2. 修Server配置(eureka server)

 1 eureka:
 2   server:
 3     # 禁用readOnlyCacheMap
 4     useReadOnlyResponseCache: false
 5     # 主動失效檢測間隔, 默認60s
 6     evictionIntervalTimerInMs: 5000
 7   instance:
 8     # eureka服務器的標識,如果是集群就可以寫成 eurekaSer1,eurekaSer2,eurekaSer3..
 9     hostname: eureka-server
10     health-check-url-path: /actuator/health
11   client:
12     # 開啟客戶端存活狀態監測
13     healthcheck:
14       enabled: true
15     registerWithEureka: false
16     fetchRegistry: false

  縮短失效檢測的實現,同時禁用readOnlye緩存。 eureka server 存在三級緩存 ,均是純內存操作,詳細見下圖

(1)registry(ConcurrentMap):注冊表
(2)readWriteCacheMap(GuavaCache):讀寫緩存
(3)readOnlyCacheMap(ConcurrentMap):只讀緩存

 
        
b、Service先下線,再停機
1、增加Service 下線端點
 1 @ConfigurationProperties(prefix = "endpoints.offline")
 2 public class OfflineEndpoint extends AbstractEndpoint<String> {
 3 
 4     public OfflineEndpoint() {
 5         super("offline", false);
 6     }
 7 
 8 
 9     @Override
10     public String invoke() {
11         String remoteIp = IPUtils.getIp();
12         String localIp = IPUtils.getLocalIp();
13         log.info("remoteIp:{} trigger service offline", remoteIp);
14         if(localIp.substring(0, localIp.lastIndexOf(".")).equals(remoteIp.substring(0, remoteIp.lastIndexOf(".")))) {
15             log.info("service start execute offline");
16             DiscoveryManager.getInstance().shutdownComponent();
17             try {
18                 Thread.sleep(10000);
19             } catch (InterruptedException e) {
20                 log.error("sleep exception",e);
21                 throw new RuntimeException(e);
22             }
23             log.info("service end execute offline");
24             return "SUCCESS";
25         } else {
26             log.warn("remoteIp:{} localIp:{} not trigger service ll_offline", remoteIp, localIp);
27             return "NOT_ALLOW";
28         }
29 
30     }
31 }
View Code

    2、利用pod preStop hook

1  lifecycle:
2           preStop:
3             httpGet:
4               port: 9494 
5               scheme: HTTP
6               path: offline

 c、Spring Cloud升級流程總結

   針對容器化RollingUpdate,Service 舊版本A,新版本A1發布流程如下:

   1、新版本容器Service A1,而在Service A1啟動后就會注冊到Eureka Server,

   2、Service A1,只有容器探針檢測成功后,才會停止舊的容器Service A。所以此時 Service A1 和 Service A都注冊在 Eureka Server上,接受流量

   3、Service A1,容器探測成功,下線Service A

   4、Service A 觸發 preStop的offline操作,將Service A 從Eureka Server中下線,直至緩存更新完成

   5、Service A停止,Service A1 上限,完成單次服務滾動更新

 

基於k8s service 負載均衡的優雅停機

  實例注冊:容器啟動成功並不會注冊到service,只有需要容器readinessPro成功后,才會注冊到service。

  實例注銷:容器執行preStop的同時就會將實例信息從service注銷

  k8s Deployment本身就支持Rolling update,所以這里優雅停機:可以先擴容到2個實例,然后再縮容到1個實例,實現單服務的滾動更新

     



         


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM