Eureka 緩存機制詳細配置


https://blog.csdn.net/qwe86314/article/details/94963865

上節為大家介紹了 Eureka 的工作原理,其中提到了 Eureka Server 內部有二層緩存機制,那這些機制是如何工作的,以及 Eureka Server 是如何存儲服務的注冊信息,本節會給大家揭曉。

Eureka 在使用過程中有一些非常重要的配置項,本節也會整理出來,方便大家以后在生產環境根據項目場景來調整。

Eureka Server 數據存儲

我們知道 Eureka Server 在運行期間就是一個普通的 Java 項目,並沒有使用數據庫之類的存儲軟件,那么在運行期間是如何存儲數據的呢?

Eureka Server 的數據存儲分了兩層:數據存儲層和緩存層。數據存儲層記錄注冊到 Eureka Server 上的服務信息,緩存層是經過包裝后的數據,可以直接在 Eureka Client 調用時返回。我們先來看看數據存儲層的數據結構。

Eureka Server 的數據存儲層是雙層的 ConcurrentHashMap,我們知道 ConcurrentHashMap 是線程安全高效的 Map 集合。

private final ConcurrentHashMap<String, Map<String, Lease<InstanceInfo>>> registry= new ConcurrentHashMap<String, Map<String, Lease<InstanceInfo>>>();

第一層的 ConcurrentHashMap 的 key=spring.application.name 也就是客戶端實例注冊的應用名;value 為嵌套的 ConcurrentHashMap。

第二層嵌套的 ConcurrentHashMap 的 key=instanceId 也就是服務的唯一實例 ID,value 為 Lease 對象,Lease 對象存儲着這個實例的所有注冊信息,包括 ip 、端口、屬性等。

根據這個存儲結構我們可以發現,Eureka Server 第一層都是存儲着所有的服務名,以及服務名對應的實例信息,也就是說第一層都是按照服務應用名這個維度來切分存儲:

應用名1:應用1實例 Map
應該名2:應用2實例 Map
...

第二層是根據實例的唯一 ID 來存儲的,那么按照這個結構最終的存儲數據格式為:

                :  應用1實例A:實例A的注冊信息 
應用名1:應用1實例:  應用1實例B:實例B的注冊信息 
                :  應用1實例C:實例C的注冊信息
                :  ....
-----------------              
                :  應用2實例F:實例F的注冊信息 
應該名2:應用2實例:  應用2實例G:實例G的注冊信息 
                :  ... 

...

 

數據存儲層數據結構如下圖所示:

在這里插入圖片描述
當如服務的狀態發生變更時,會同步 Eureka Server 中的 registry 數據信息,比如服務注冊、剔除服務時。

Eureka Server 緩存機制

Eureka Server 為了提供響應效率,提供了兩層的緩存結構,將 Eureka Client 所需要的注冊信息,直接存儲在緩存結構中。

第一層緩存:readOnlyCacheMap,本質上是 ConcurrentHashMap,依賴定時從 readWriteCacheMap 同步數據,默認時間為 30 秒。

readOnlyCacheMap : 是一個 CurrentHashMap 只讀緩存,這個主要是為了供客戶端獲取注冊信息時使用,其緩存更新,依賴於定時器的更新,通過和 readWriteCacheMap 的值做對比,如果數據不一致,則以 readWriteCacheMap 的數據為准。

第二層緩存:readWriteCacheMap,本質上是 Guava 緩存。

readWriteCacheMap:readWriteCacheMap 的數據主要同步於存儲層。當獲取緩存時判斷緩存中是否沒有數據,如果不存在此數據,則通過 CacheLoader 的 load 方法去加載,加載成功之后將數據放入緩存,同時返回數據。

readWriteCacheMap 緩存過期時間,默認為 180 秒,當服務下線、過期、注冊、狀態變更,都會來清除此緩存中的數據。

Eureka Client 獲取全量或者增量的數據時,會先從一級緩存中獲取;如果一級緩存中不存在,再從二級緩存中獲取;如果二級緩存也不存在,這時候先將存儲層的數據同步到緩存中,再從緩存中獲取。

通過 Eureka Server 的二層緩存機制,可以非常有效地提升 Eureka Server 的響應時間,通過數據存儲層和緩存層的數據切割,根據使用場景來提供不同的數據支持。

其它緩存設計

除過 Eureka Server 端存在緩存外,Eureka Client 也同樣存在着緩存機制,Eureka Client 啟動時會全量拉取服務列表,啟動后每隔 30 秒從 Eureka Server 量獲取服務列表信息,並保持在本地緩存中。

Eureka Client 增量拉取失敗,或者增量拉取之后對比 hashcode 發現不一致,就會執行全量拉取,這樣避免了網絡某時段分片帶來的問題,同樣會更新到本地緩存。

同時對於服務調用,如果涉及到 ribbon 負載均衡,那么 ribbon 對於這個實例列表也有自己的緩存,這個緩存定時(默認30秒)從 Eureka Client 的緩存更新。

這么多的緩存機制可能就會造成一些問題,一個服務啟動后可能最長需要 90s 才能被其它服務感知到:

1、首先,Eureka Server 維護每 30s 更新的響應緩存

2、Eureka Client 對已經獲取到的注冊信息也做了 30s 緩存

3、負載均衡組件 Ribbon 也有 30s 緩存

這三個緩存加起來,就有可能導致服務注冊最長延遲 90s ,這個需要我們在特殊業務場景中注意其產生的影響。

Eureka 常用配置

在 Spring Cloud 官網查看 Spring Cloud Netflix 的介紹時,會出現以下幾個名字,在這里給大家一一介紹:

·Eureka Server,Eureka 作為注冊中心的角色,稱之為 Eureka Server。
·Eureka Client,這個比較好理解,前面的文章介紹過注冊到 Eureka 的客戶端。
·Eureka Instance,可以稱之為 Eureka 實例,注冊到服務中心的每一個單獨的示例,比如 ip 為 192.168.0.1 、端口為 8080 的一個實例。
·Eureka service,Eureka service 其實是 Eureka Instance 的一個抽象,比如是訂單服務,有可能訂單服務是由多個訂單實例(Eureka Instance)組成,具體表現為配置應用名相同的一組實例。

·接下來我們就來了解上面這幾個概念的常用配置項,Eureka service 作為抽象的概念沒有具體的配置項,其它三個均可配置。

Eureka Server常用配置

#服務端開啟自我保護模式,前面章節有介紹
eureka.server.enable-self-preservation=true
#掃描失效服務的間隔時間(單位毫秒,默認是60*1000)即60秒
eureka.server.eviction-interval-timer-in-ms= 60000
#間隔多長時間,清除過期的 delta 數據
eureka.server.delta-retention-timer-interval-in-ms=0
#請求頻率限制器
eureka.server.rate-limiter-burst-size=10
#是否開啟請求頻率限制器
eureka.server.rate-limiter-enabled=false
#請求頻率的平均值
eureka.server.rate-limiter-full-fetch-average-rate=100
#是否對標准的client進行頻率請求限制。如果是false,則只對非標准client進行限制
eureka.server.rate-limiter-throttle-standard-clients=false
#注冊服務、拉去服務列表數據的請求頻率的平均值
eureka.server.rate-limiter-registry-fetch-average-rate=500
#設置信任的client list
eureka.server.rate-limiter-privileged-clients=
#在設置的時間范圍類,期望與client續約的百分比。
eureka.server.renewal-percent-threshold=0.85
#多長時間更新續約的閾值
eureka.server.renewal-threshold-update-interval-ms=0
#對於緩存的注冊數據,多長時間過期
eureka.server.response-cache-auto-expiration-in-seconds=180
#多長時間更新一次緩存中的服務注冊數據
eureka.server.response-cache-update-interval-ms=0
#緩存增量數據的時間,以便在檢索的時候不丟失信息
eureka.server.retention-time-in-m-s-in-delta-queue=0
#當時間戳不一致的時候,是否進行同步
eureka.server.sync-when-timestamp-differs=true
#是否采用只讀緩存策略,只讀策略對於緩存的數據不會過期。
eureka.server.use-read-only-response-cache=true


################server node 與 node 之間關聯的配置#####################33
#發送復制數據是否在request中,總是壓縮
eureka.server.enable-replicated-request-compression=false
#指示群集節點之間的復制是否應批處理以提高網絡效率。
eureka.server.batch-replication=false
#允許備份到備份池的最大復制事件數量。而這個備份池負責除狀態更新的其他事件。可以根據內存大小,超時和復制流量,來設置此值得大小
eureka.server.max-elements-in-peer-replication-pool=10000
#允許備份到狀態備份池的最大復制事件數量
eureka.server.max-elements-in-status-replication-pool=10000
#多個服務中心相互同步信息線程的最大空閑時間
eureka.server.max-idle-thread-age-in-minutes-for-peer-replication=15
#狀態同步線程的最大空閑時間
eureka.server.max-idle-thread-in-minutes-age-for-status-replication=15
#服務注冊中心各個instance相互復制數據的最大線程數量
eureka.server.max-threads-for-peer-replication=20
#服務注冊中心各個instance相互復制狀態數據的最大線程數量
eureka.server.max-threads-for-status-replication=1
#instance之間復制數據的通信時長
eureka.server.max-time-for-replication=30000
#正常的對等服務instance最小數量。-1表示服務中心為單節點。
eureka.server.min-available-instances-for-peer-replication=-1
#instance之間相互復制開啟的最小線程數量
eureka.server.min-threads-for-peer-replication=5
#instance之間用於狀態復制,開啟的最小線程數量
eureka.server.min-threads-for-status-replication=1
#instance之間復制數據時可以重試的次數
eureka.server.number-of-replication-retries=5
#eureka節點間間隔多長時間更新一次數據。默認10分鍾。
eureka.server.peer-eureka-nodes-update-interval-ms=600000
#eureka服務狀態的相互更新的時間間隔。
eureka.server.peer-eureka-status-refresh-time-interval-ms=0
#eureka對等節點間連接超時時間
eureka.server.peer-node-connect-timeout-ms=200
#eureka對等節點連接后的空閑時間
eureka.server.peer-node-connection-idle-timeout-seconds=30
#節點間的讀數據連接超時時間
eureka.server.peer-node-read-timeout-ms=200
#eureka server 節點間連接的總共最大數量
eureka.server.peer-node-total-connections=1000
#eureka server 節點間連接的單機最大數量
eureka.server.peer-node-total-connections-per-host=10
#在服務節點啟動時,eureka嘗試獲取注冊信息的次數
eureka.server.registry-sync-retries=
#在服務節點啟動時,eureka多次嘗試獲取注冊信息的間隔時間
eureka.server.registry-sync-retry-wait-ms=
#當eureka server啟動的時候,不能從對等節點獲取instance注冊信息的情況,應等待多長時間。
eureka.server.wait-time-in-ms-when-sync-empty=0

 

Eureka Client 常用配置

#該客戶端是否可用
eureka.client.enabled=true
#實例是否在eureka服務器上注冊自己的信息以供其他服務發現,默認為true
eureka.client.register-with-eureka=false
#此客戶端是否獲取eureka服務器注冊表上的注冊信息,默認為true
eureka.client.fetch-registry=false
#是否過濾掉,非UP的實例。默認為true
eureka.client.filter-only-up-instances=true
#與Eureka注冊服務中心的通信zone和url地址
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/

#client連接Eureka服務端后的空閑等待時間,默認為30 秒
eureka.client.eureka-connection-idle-timeout-seconds=30
#client連接eureka服務端的連接超時時間,默認為5秒
eureka.client.eureka-server-connect-timeout-seconds=5
#client對服務端的讀超時時長
eureka.client.eureka-server-read-timeout-seconds=8
#client連接all eureka服務端的總連接數,默認200
eureka.client.eureka-server-total-connections=200
#client連接eureka服務端的單機連接數量,默認50
eureka.client.eureka-server-total-connections-per-host=50
#執行程序指數回退刷新的相關屬性,是重試延遲的最大倍數值,默認為10
eureka.client.cache-refresh-executor-exponential-back-off-bound=10
#執行程序緩存刷新線程池的大小,默認為5
eureka.client.cache-refresh-executor-thread-pool-size=2
#心跳執行程序回退相關的屬性,是重試延遲的最大倍數值,默認為10
eureka.client.heartbeat-executor-exponential-back-off-bound=10
#心跳執行程序線程池的大小,默認為5
eureka.client.heartbeat-executor-thread-pool-size=5
# 詢問Eureka服務url信息變化的頻率(s),默認為300秒
eureka.client.eureka-service-url-poll-interval-seconds=300
#最初復制實例信息到eureka服務器所需的時間(s),默認為40秒
eureka.client.initial-instance-info-replication-interval-seconds=40
#間隔多長時間再次復制實例信息到eureka服務器,默認為30秒
eureka.client.instance-info-replication-interval-seconds=30
#從eureka服務器注冊表中獲取注冊信息的時間間隔(s),默認為30秒
eureka.client.registry-fetch-interval-seconds=30

# 獲取實例所在的地區。默認為us-east-1
eureka.client.region=us-east-1
#實例是否使用同一zone里的eureka服務器,默認為true,理想狀態下,eureka客戶端與服務端是在同一zone下
eureka.client.prefer-same-zone-eureka=true
# 獲取實例所在的地區下可用性的區域列表,用逗號隔開。(AWS)
eureka.client.availability-zones.china=defaultZone,defaultZone1,defaultZone2
#eureka服務注冊表信息里的以逗號隔開的地區名單,如果不這樣返回這些地區名單,則客戶端啟動將會出錯。默認為null
eureka.client.fetch-remote-regions-registry=
#服務器是否能夠重定向客戶端請求到備份服務器。 如果設置為false,服務器將直接處理請求,如果設置為true,它可能發送HTTP重定向到客戶端。默認為false
eureka.client.allow-redirects=false
#客戶端數據接收
eureka.client.client-data-accept=
#增量信息是否可以提供給客戶端看,默認為false
eureka.client.disable-delta=false
#eureka服務器序列化/反序列化的信息中獲取“_”符號的的替換字符串。默認為“__“
eureka.client.escape-char-replacement=__
#eureka服務器序列化/反序列化的信息中獲取“$”符號的替換字符串。默認為“_-”
eureka.client.dollar-replacement="_-"
#當服務端支持壓縮的情況下,是否支持從服務端獲取的信息進行壓縮。默認為true
eureka.client.g-zip-content=true
#是否記錄eureka服務器和客戶端之間在注冊表的信息方面的差異,默認為false
eureka.client.log-delta-diff=false
# 如果設置為true,客戶端的狀態更新將會點播更新到遠程服務器上,默認為true
eureka.client.on-demand-update-status-change=true
#此客戶端只對一個單一的VIP注冊表的信息感興趣。默認為null
eureka.client.registry-refresh-single-vip-address=
#client是否在初始化階段強行注冊到服務中心,默認為false
eureka.client.should-enforce-registration-at-init=false
#client在shutdown的時候是否顯示的注銷服務從服務中心,默認為true
eureka.client.should-unregister-on-shutdown=true

Eureka Instance 常用配置

#服務注冊中心實例的主機名
eureka.instance.hostname=localhost
#注冊在Eureka服務中的應用組名
eureka.instance.app-group-name=
#注冊在的Eureka服務中的應用名稱
eureka.instance.appname=
#該實例注冊到服務中心的唯一ID
eureka.instance.instance-id=
#該實例的IP地址
eureka.instance.ip-address=
#該實例,相較於hostname是否優先使用IP
eureka.instance.prefer-ip-address=false

總結

本節課給大家介紹了 Eureka 數據的存儲原理,以及內部巧妙的二級緩存機制,在我們學習 Eureka 的內部存儲原理時,同時了解到 Eureka 內部的精妙設計,后期我們在項目中也可借鑒它的實現機制。

本節的最后也給大家羅列了一些 Eureka 的常用配置,方便大家在日常工作中根據需要來調整。


免責聲明!

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



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