一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

Spring Cloud Eureka 服務(wù)實現(xiàn)不停機(jī)(Zero

 vnxy001 2021-03-09

問題

互聯(lián)網(wǎng)產(chǎn)品高速迭代,通常伴隨著高頻次的版本發(fā)布。部署新版上線需要重啟服務(wù),直接 kill 服務(wù)進(jìn)程可能會造成服務(wù)短暫不可用,從而影響到正在使用的用戶。

Spring Cloud 項目中一般會用到 Ribbon 作為負(fù)載均衡,那么是不是只要保證每個服務(wù)部署多臺服務(wù)器,發(fā)布時采用 Rolling Update 分批次部署,保證一部分服務(wù)器正常提供服務(wù)的同時發(fā)布另一部分服務(wù)器,Ribbon 就能自動切換,保證服務(wù)的不間斷?然而并不是。

產(chǎn)生原因

所有服務(wù)的狀態(tài)保存在注冊中心,即 Eureka Server。一個服務(wù)要想獲取其他服務(wù)的實例列表和狀態(tài),需要通過 Eureka Client 定時從 Eureka Server 中獲取并緩存下來,默認(rèn)時間間隔是30秒。Eureka Client 和 Eureka Server 是通過 HTTP 協(xié)議通信,請求由 Eureka Client 發(fā)起,而不是基于長連接或者 Eureka Server 主動推送,所以無法立即知道其他服務(wù)狀態(tài)變更。

即使同一個服務(wù)部署多臺機(jī)器,每臺機(jī)器依次發(fā)布,當(dāng)其中一個服務(wù)實例重啟時,服務(wù)調(diào)用方是無法第一時間知道的,所以還是會調(diào)用到這臺暫時無法提供服務(wù)的實例上。這樣會造成短暫的訪問失敗,這段時間也會對正在使用產(chǎn)品的用戶造成一定的影響。

解決方案

基于以上的原因,在部署應(yīng)用時應(yīng)該按照以下步驟進(jìn)行(為了簡單起見,假設(shè)一個應(yīng)用部署兩個實例):

  1. 將服務(wù)的一個實例在注冊中心的狀態(tài)設(shè)置為 DOWN
  2. 等待一段時間,直到其他服務(wù)緩存刷新,不再調(diào)用到這臺服務(wù)器上
  3. 停止服務(wù),更新代碼,重新啟動,等待,直到啟動成功

完成后,再重復(fù)以上步驟部署另一個實例。

第一步:修改服務(wù)實例狀態(tài)為 DOWN

有兩種方案可以修改實例的狀態(tài),選擇其一即可:

  1. 直接調(diào)用 Eureka Server API 修改:PUT /eureka/apps/{appID}/{instanceID}/status?value=DOWN
  2. 調(diào)用服務(wù)實例對應(yīng)的 actuator endpoint:/service-registry

我更偏向使用方法二,對應(yīng)的命令:

1
curl -H "Content-Type:application/json" -X POST http://{host:port}/actuator/service-registry?status=DOWN

 

如果 actuator endpoint 加了 Spring Security Basic 認(rèn)證,則還需要加上用戶名和密碼:

1
curl -H "Content-Type:application/json" -X POST -u {username}:{password} http://{host:port}/actuator/service-registry?status=DOWN

 

第二步:等待其他服務(wù)緩存刷新

具體要等多久,其他調(diào)用者的請求才會不再訪問到這臺狀態(tài)為 DOWN 的實例?這里涉及到三個配置項:

  • eureka.client.registryFetchIntervalSeconds Eureka 客戶端每隔多久去 Eureka 服務(wù)器拉取最新的注冊信息,默認(rèn)值 30(秒)。
  • ribbon.ServerListRefreshInterval Ribbon 的緩存刷新間隔時間,默認(rèn) 30000(毫秒)。Eureka 客戶端拉取到最新注冊信息后,Ribbon、Feign 等組件不會立即生效,是因為 Ribbon 還有一層緩存。
  • eureka.server.responseCacheUpdateIntervalMs Eureka Server 返回最新的注冊信息的接口緩存刷新時間間隔,默認(rèn) 30000(毫秒)。有時候會看到 Eureka 頁面和 /eureka/apps 接口的服務(wù)狀態(tài)不一致,就是因為 /eureka/apps 接口默認(rèn)會有 30 秒緩存。

在默認(rèn)情況下,當(dāng)一個服務(wù)狀態(tài)改為 DOWN,最長可能需要 30+30+30 秒,所有的緩存才會刷新,其他調(diào)用者才不會調(diào)用到這個狀態(tài)為 DOWN 的實例。這就意味著修改服務(wù)實例狀態(tài)為 DOWN 后需要等待 90 秒,才能進(jìn)行下一步操作。

為了讓部署時間縮短,可以將以上三個配置項都修改為5秒:

Eureka Server:

1
2
3
eureka:
  server:
    responseCacheUpdateIntervalMs: 5000

 

Eureka Client(即各個服務(wù)):

1
2
3
4
5
ribbon:
  ServerListRefreshInterval: 5000
eureka:
  client:
    registryFetchIntervalSeconds: 5

 

完成以上配置,部署時將實例狀態(tài)設(shè)為 DOWN 后,只需要等待 15 秒即可停止進(jìn)程:

1
sleep 15s

 

第三步:實例部署

這一步主要需要注意

  • 盡量不要使用 kill -9 pid 強(qiáng)制殺掉進(jìn)程,而應(yīng)該使用 kill pid 或者 kill -15 pid 關(guān)閉進(jìn)程。使用 kill pid 或者 kill -15 pid 關(guān)閉進(jìn)程之前,Eureka Client 會給 Eureka Server 請求刪除自己,后續(xù)服務(wù)再次啟動后會重新注冊為 UP 狀態(tài)。如果使用 kill -9 pid 強(qiáng)制殺掉進(jìn)程,Eureka Client 沒有辦法注銷自己,Eureka Server 就不知道該實例已下線,直到長時間收不到心跳才會刪除該實例。如果在 Eureka Server 刪除實例之前實例啟動了,那么它的狀態(tài)還是會保持 DOWN 狀態(tài)。如果確實需要用到 kill -9 pid 強(qiáng)制殺掉進(jìn)程,那么服務(wù)重啟后需要再通過第一步的方式將實例狀態(tài)設(shè)為 UP。
  • 服務(wù)啟動后,需要等待并確認(rèn)啟動成功后,才可以開始部署下一臺服務(wù)器。這里我們可以定時去請求 Spring Boot 提供的 actuator endpoint /health 接口,例如每隔 1 秒請求一次,直到接口可以正常訪問,即可認(rèn)為服務(wù)啟動成功。

本文基于 Spring Boot 2.1.x 及 Spring Cloud Greenwich 版本

問題

互聯(lián)網(wǎng)產(chǎn)品高速迭代,通常伴隨著高頻次的版本發(fā)布。部署新版上線需要重啟服務(wù),直接 kill 服務(wù)進(jìn)程可能會造成服務(wù)短暫不可用,從而影響到正在使用的用戶。

Spring Cloud 項目中一般會用到 Ribbon 作為負(fù)載均衡,那么是不是只要保證每個服務(wù)部署多臺服務(wù)器,發(fā)布時采用 Rolling Update 分批次部署,保證一部分服務(wù)器正常提供服務(wù)的同時發(fā)布另一部分服務(wù)器,Ribbon 就能自動切換,保證服務(wù)的不間斷?然而并不是。

產(chǎn)生原因

所有服務(wù)的狀態(tài)保存在注冊中心,即 Eureka Server。一個服務(wù)要想獲取其他服務(wù)的實例列表和狀態(tài),需要通過 Eureka Client 定時從 Eureka Server 中獲取并緩存下來,默認(rèn)時間間隔是30秒。Eureka Client 和 Eureka Server 是通過 HTTP 協(xié)議通信,請求由 Eureka Client 發(fā)起,而不是基于長連接或者 Eureka Server 主動推送,所以無法立即知道其他服務(wù)狀態(tài)變更。

即使同一個服務(wù)部署多臺機(jī)器,每臺機(jī)器依次發(fā)布,當(dāng)其中一個服務(wù)實例重啟時,服務(wù)調(diào)用方是無法第一時間知道的,所以還是會調(diào)用到這臺暫時無法提供服務(wù)的實例上。這樣會造成短暫的訪問失敗,這段時間也會對正在使用產(chǎn)品的用戶造成一定的影響。

解決方案

基于以上的原因,在部署應(yīng)用時應(yīng)該按照以下步驟進(jìn)行(為了簡單起見,假設(shè)一個應(yīng)用部署兩個實例):

  1. 將服務(wù)的一個實例在注冊中心的狀態(tài)設(shè)置為 DOWN
  2. 等待一段時間,直到其他服務(wù)緩存刷新,不再調(diào)用到這臺服務(wù)器上
  3. 停止服務(wù),更新代碼,重新啟動,等待,直到啟動成功

完成后,再重復(fù)以上步驟部署另一個實例。

第一步:修改服務(wù)實例狀態(tài)為 DOWN

有兩種方案可以修改實例的狀態(tài),選擇其一即可:

  1. 直接調(diào)用 Eureka Server API 修改:PUT /eureka/apps/{appID}/{instanceID}/status?value=DOWN
  2. 調(diào)用服務(wù)實例對應(yīng)的 actuator endpoint:/service-registry

我更偏向使用方法二,對應(yīng)的命令:

1
curl -H "Content-Type:application/json" -X POST http://{host:port}/actuator/service-registry?status=DOWN

 

如果 actuator endpoint 加了 Spring Security Basic 認(rèn)證,則還需要加上用戶名和密碼:

1
curl -H "Content-Type:application/json" -X POST -u {username}:{password} http://{host:port}/actuator/service-registry?status=DOWN

 

第二步:等待其他服務(wù)緩存刷新

具體要等多久,其他調(diào)用者的請求才會不再訪問到這臺狀態(tài)為 DOWN 的實例?這里涉及到三個配置項:

  • eureka.client.registryFetchIntervalSeconds Eureka 客戶端每隔多久去 Eureka 服務(wù)器拉取最新的注冊信息,默認(rèn)值 30(秒)。
  • ribbon.ServerListRefreshInterval Ribbon 的緩存刷新間隔時間,默認(rèn) 30000(毫秒)。Eureka 客戶端拉取到最新注冊信息后,Ribbon、Feign 等組件不會立即生效,是因為 Ribbon 還有一層緩存。
  • eureka.server.responseCacheUpdateIntervalMs Eureka Server 返回最新的注冊信息的接口緩存刷新時間間隔,默認(rèn) 30000(毫秒)。有時候會看到 Eureka 頁面和 /eureka/apps 接口的服務(wù)狀態(tài)不一致,就是因為 /eureka/apps 接口默認(rèn)會有 30 秒緩存。

在默認(rèn)情況下,當(dāng)一個服務(wù)狀態(tài)改為 DOWN,最長可能需要 30+30+30 秒,所有的緩存才會刷新,其他調(diào)用者才不會調(diào)用到這個狀態(tài)為 DOWN 的實例。這就意味著修改服務(wù)實例狀態(tài)為 DOWN 后需要等待 90 秒,才能進(jìn)行下一步操作。

為了讓部署時間縮短,可以將以上三個配置項都修改為5秒:

Eureka Server:

1
2
3
eureka:
  server:
    responseCacheUpdateIntervalMs: 5000

 

Eureka Client(即各個服務(wù)):

1
2
3
4
5
ribbon:
  ServerListRefreshInterval: 5000
eureka:
  client:
    registryFetchIntervalSeconds: 5

 

完成以上配置,部署時將實例狀態(tài)設(shè)為 DOWN 后,只需要等待 15 秒即可停止進(jìn)程:

1
sleep 15s

 

第三步:實例部署

這一步主要需要注意

  • 盡量不要使用 kill -9 pid 強(qiáng)制殺掉進(jìn)程,而應(yīng)該使用 kill pid 或者 kill -15 pid 關(guān)閉進(jìn)程。使用 kill pid 或者 kill -15 pid 關(guān)閉進(jìn)程之前,Eureka Client 會給 Eureka Server 請求刪除自己,后續(xù)服務(wù)再次啟動后會重新注冊為 UP 狀態(tài)。如果使用 kill -9 pid 強(qiáng)制殺掉進(jìn)程,Eureka Client 沒有辦法注銷自己,Eureka Server 就不知道該實例已下線,直到長時間收不到心跳才會刪除該實例。如果在 Eureka Server 刪除實例之前實例啟動了,那么它的狀態(tài)還是會保持 DOWN 狀態(tài)。如果確實需要用到 kill -9 pid 強(qiáng)制殺掉進(jìn)程,那么服務(wù)重啟后需要再通過第一步的方式將實例狀態(tài)設(shè)為 UP。
  • 服務(wù)啟動后,需要等待并確認(rèn)啟動成功后,才可以開始部署下一臺服務(wù)器。這里我們可以定時去請求 Spring Boot 提供的 actuator endpoint /health 接口,例如每隔 1 秒請求一次,直到接口可以正常訪問,即可認(rèn)為服務(wù)啟動成功。

本文基于 Spring Boot 2.1.x 及 Spring Cloud Greenwich 版本

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    国产成人精品99在线观看| 中文字幕日韩一区二区不卡| 91亚洲国产成人久久精品麻豆| 国产又大又黄又粗的黄色| 久久精品中文扫妇内射| 成人国产激情在线视频| 久久国产成人精品国产成人亚洲| 亚洲中文字幕在线乱码av| 久久人人爽人人爽大片av| 国产欧美日韩精品成人专区| 2019年国产最新视频| 亚洲中文在线男人的天堂| 风间中文字幕亚洲一区| 人妻少妇久久中文字幕久久| 不卡免费成人日韩精品| 欧美精品女同一区二区| 91播色在线免费播放| 国产男女激情在线视频| 亚洲欧美一二区日韩高清在线| 日韩欧美三级视频在线| 国产欧美日韩精品一区二| 国产成人在线一区二区三区| 中国美女草逼一级黄片视频| 五月天丁香婷婷一区二区| 国产精品成人免费精品自在线观看| 高跟丝袜av在线一区二区三区| 亚洲第一区二区三区女厕偷拍| 四季av一区二区播放| 亚洲欧洲一区二区综合精品| 亚洲精品国产福利在线| 国产人妻精品区一区二区三区| 黄色国产自拍在线观看| 麻豆蜜桃星空传媒在线观看| 日韩欧美国产精品自拍| 欧美午夜不卡在线观看| 丁香六月婷婷基地伊人| 日韩精品视频免费观看| 高清不卡一卡二卡区在线| 国产日产欧美精品大秀| 69老司机精品视频在线观看| 日韩1区二区三区麻豆|