天天看點

eureka 之前的服務如何關閉_詳解Eureka 緩存機制

引言

Eureka是Netflix開源的、用于實作服務注冊和發現的服務。Spring Cloud Eureka基于Eureka進行二次封裝,增加了更人性化的UI,使用更為友善。但是由于Eureka本身存在較多緩存,服務狀态更新滞後,最常見的狀況是:服務下線後狀态沒有及時更新,服務消費者調用到已下線的服務導緻請求失敗。本文基于Spring Cloud Eureka 1.4.4.RELEASE,在預設region和zone的前提下,介紹Eureka的緩存機制。

一、AP特性

從CAP理論看,Eureka是一個AP系統,優先保證可用性(A)和分區容錯性(P),不保證強一緻性(C),隻保證最終一緻性,是以在架構中設計了較多緩存。

eureka 之前的服務如何關閉_詳解Eureka 緩存機制

Eureka高可用架構

二、服務狀态

Eureka服務狀态enum類:com.netflix.appinfo.InstanceInfo.InstanceStatus

eureka 之前的服務如何關閉_詳解Eureka 緩存機制

三、Eureka Server

在Eureka高可用架構中,Eureka Server也可以作為Client向其他server注冊,多節點互相注冊組成Eureka叢集,叢集間互相視為peer。Eureka Client向Server注冊、續約、更新狀态時,接受節點更新自己的服務注冊資訊後,逐個同步至其他peer節點。

【注意】如果server-A向server-B節點單向注冊,則server-A視server-B為peer節點,server-A接受的資料會同步給server-B,但server-B接受的資料不會同步給server-A。

3.1 緩存機制

Eureka Server存在三個變量:(registry、readWriteCacheMap、readOnlyCacheMap)儲存服務注冊資訊,預設情況下定時任務每30s将readWriteCacheMap同步至readOnlyCacheMap,每60s清理超過90s未續約的節點,Eureka Client每30s從readOnlyCacheMap更新服務注冊資訊,而UI則從registry更新服務注冊資訊。

eureka 之前的服務如何關閉_詳解Eureka 緩存機制

三級緩存

eureka 之前的服務如何關閉_詳解Eureka 緩存機制

緩存相關配置

eureka 之前的服務如何關閉_詳解Eureka 緩存機制

關鍵類

eureka 之前的服務如何關閉_詳解Eureka 緩存機制

四、Eureka Client

Eureka Client存在兩種角色:服務提供者和服務消費者,作為服務消費者一般配合Ribbon或Feign(Feign内部使用Ribbon)使用。Eureka Client啟動後,作為服務提供者立即向Server注冊,預設情況下每30s續約(renew);作為服務消費者立即向Server全量更新服務注冊資訊,預設情況下每30s增量更新服務注冊資訊;Ribbon延時1s向Client擷取使用的服務注冊資訊,預設每30s更新使用的服務注冊資訊,隻儲存狀态為UP的服務。

二級緩存

eureka 之前的服務如何關閉_詳解Eureka 緩存機制

緩存相關配置

eureka 之前的服務如何關閉_詳解Eureka 緩存機制

關鍵類

eureka 之前的服務如何關閉_詳解Eureka 緩存機制

五、預設配置下服務消費者最長感覺時間

eureka 之前的服務如何關閉_詳解Eureka 緩存機制

考慮如下情況:

  • 0s時服務未通知Eureka Client直接下線;
  • 29s時第一次過期檢查evict未超過90s;
  • 89s時第二次過期檢查evict未超過90s;
  • 149s時第三次過期檢查evict未續約時間超過了90s,故将該服務執行個體從registry和readWriteCacheMap中删除;
  • 179s時定時任務從readWriteCacheMap更新至readOnlyCacheMap;
  • 209s時Eureka Client從Eureka Server的readOnlyCacheMap更新;
  • 239s時Ribbon從Eureka Client更新。

是以,極限情況下服務消費者最長感覺時間将無限趨近240s。

eureka 之前的服務如何關閉_詳解Eureka 緩存機制

六、應對措施

服務注冊中心在選擇使用Eureka時說明已經接受了其優先保證可用性(A)和分區容錯性(P)、不保證強一緻性(C)的特點。如果需要優先保證強一緻性(C),則應該考慮使用ZooKeeper等CP系統作為服務注冊中心。分布式系統中一般配置多節點,單個節點服務上線的狀态更新滞後并沒有什麼影響,這裡主要考慮服務下線後狀态更新滞後的應對措施。

6.1 Eureka Server

1.縮短readOnlyCacheMap更新周期。縮短該定時任務周期可減少滞後時間。

eureka.server.responsecCacheUpdateIntervalMs: 10000 # Eureka Server readOnlyCacheMap更新周期
           

2.關閉readOnlyCacheMap。中小型系統可以考慮該方案,Eureka Client直接從readWriteCacheMap更新服務注冊資訊。

eureka.server.useReadOnlyResponseCache: false # 是否使用readOnlyCacheMap
           

6.2 Eureka Client

1.服務消費者使用容錯機制。如Spring Cloud Retry和Hystrix,Ribbon、Feign、Zuul都可以配置Retry,服務消費者通路某個已下線節點時一般報ConnectTimeout,這時可以通過Retry機制重試下一個節點。

2.服務消費者縮短更新周期。Eureka Client和Ribbon二級緩存影響狀态更新,縮短這兩個定時任務周期可減少滞後時間,例如配置:

eureka.client.registryFetchIntervalSeconds: 5 # Eureka Client更新周期 ribbon.ServerListRefreshInterval: 2000 # Ribbon更新周期
           

3.服務提供者保證服務正常下線。服務下線時使用kill或kill -15指令,避免使用kill -9指令,kill或kill -15指令殺死程序時将觸發Eureka Client的shutdown()方法,主動删除Server的registry和readWriteCacheMap中的注冊資訊,不必依賴Server的evict清除。

4.服務提供者延遲下線。服務下線之前先調用接口使Eureka Server中儲存的服務狀态為DOWN或OUT_OF_SERVICE後再下線,二者時間差根據緩存機制和配置決定,比如預設情況下調用接口後延遲90s再下線服務即可保證服務消費者不會調用已下線服務執行個體。

七、網關實作服務下線實時感覺

在軟體工程中,沒有一個問題是中間層解決不了的,而網關是服務提供者和服務消費者的中間層。以Spring Cloud Zuul網關為例,網關作為Eureka Client儲存了服務注冊資訊,服務消費者通過網關将請求轉發給服務提供者,隻需要做到服務提供者下線時通知網關在自己儲存的服務清單中使該服務失效。為了保持網關的獨立性,可實作一個獨立服務接收下線通知并協調網關叢集。下篇文章将詳細介紹網關如何實作服務下線實時感覺,敬請期待!

作者:馮永彪