天天看點

關于SpringCloud基于Rancher的優雅停服

1、通過jenkins的kubctl向Rancher釋出鏡像時。第一步在Rancher容器内設定健康檢查。通過K8S健康檢查,以雙服務node為例:能達到先啟動一個新服務,再停掉第一個舊服務;然後會自動啟動第二個新服務,再停掉一個舊服務。

具體健康檢查如下:

關于SpringCloud基于Rancher的優雅停服

 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發起服務下線的請求。

關于SpringCloud基于Rancher的優雅停服

 4、服務在強停止之前,會先向注冊中心發起下線請求。然後讓服務在停服之前先sleep 10秒。通過測試發現,服務下線前,注冊中心确實down了對應的微服務,但是jmeter測試仍然有報錯。我們猜想registry可能有緩存。

5、于是我們禁用了registry的緩存。

關于SpringCloud基于Rancher的優雅停服

6、同時,我們調整了gateway拉取registry路由清單的時長為5s,預設是30s。

關于SpringCloud基于Rancher的優雅停服

 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秒,時間依情況而定。

繼續閱讀