摘要:和二級(jí)緩存影響狀態(tài)更新,縮短這兩個(gè)定時(shí)任務(wù)周期可減少滯后時(shí)間,例如配置更新周期更新周期服務(wù)提供者保證服務(wù)正常下線。服務(wù)提供者延遲下線。
引言
Eureka是Netflix開源的、用于實(shí)現(xiàn)服務(wù)注冊(cè)和發(fā)現(xiàn)的服務(wù)。Spring Cloud Eureka基于Eureka進(jìn)行二次封裝,增加了更人性化的UI,使用更為方便。但是由于Eureka本身存在較多緩存,服務(wù)狀態(tài)更新滯后,最常見的狀況是:服務(wù)下線后狀態(tài)沒有及時(shí)更新,服務(wù)消費(fèi)者調(diào)用到已下線的服務(wù)導(dǎo)致請(qǐng)求失敗。本文基于Spring Cloud Eureka 1.4.4.RELEASE,在默認(rèn)region和zone的前提下,介紹Eureka的緩存機(jī)制。
一、AP特性從CAP理論看,Eureka是一個(gè)AP系統(tǒng),優(yōu)先保證可用性(A)和分區(qū)容錯(cuò)性(P),不保證強(qiáng)一致性(C),只保證最終一致性,因此在架構(gòu)中設(shè)計(jì)了較多緩存。
二、服務(wù)狀態(tài)Eureka服務(wù)狀態(tài)enum類:com.netflix.appinfo.InstanceInfo.InstanceStatus
狀態(tài) | 說明 | 狀態(tài) | 說明 |
---|---|---|---|
UP | 在線 | OUT_OF_SERVICE | 失效 |
DOWN | 下線 | UNKNOWN | 未知 |
STARTING | 正在啟動(dòng) |
在Eureka高可用架構(gòu)中,Eureka Server也可以作為Client向其他server注冊(cè),多節(jié)點(diǎn)相互注冊(cè)組成Eureka集群,集群間相互視為peer。Eureka Client向Server注冊(cè)、續(xù)約、更新狀態(tài)時(shí),接受節(jié)點(diǎn)更新自己的服務(wù)注冊(cè)信息后,逐個(gè)同步至其他peer節(jié)點(diǎn)。
【注意】如果server-A向server-B節(jié)點(diǎn)單向注冊(cè),則server-A視server-B為peer節(jié)點(diǎn),server-A接受的數(shù)據(jù)會(huì)同步給server-B,但server-B接受的數(shù)據(jù)不會(huì)同步給server-A。
3.1 緩存機(jī)制Eureka Server存在三個(gè)變量:(registry、readWriteCacheMap、readOnlyCacheMap)保存服務(wù)注冊(cè)信息,默認(rèn)情況下定時(shí)任務(wù)每30s將readWriteCacheMap同步至readOnlyCacheMap,每60s清理超過90s未續(xù)約的節(jié)點(diǎn),Eureka Client每30s從readOnlyCacheMap更新服務(wù)注冊(cè)信息,而UI則從registry更新服務(wù)注冊(cè)信息。
三級(jí)緩存
緩存 | 類型 | 說明 |
---|---|---|
registry | ConcurrentHashMap | 實(shí)時(shí)更新,類AbstractInstanceRegistry成員變量,UI端請(qǐng)求的是這里的服務(wù)注冊(cè)信息 |
readWriteCacheMap | Guava Cache/LoadingCache | 實(shí)時(shí)更新,類ResponseCacheImpl成員變量,緩存時(shí)間180秒 |
readOnlyCacheMap | ConcurrentHashMap | 周期更新,類ResponseCacheImpl成員變量,默認(rèn)每30s從readWriteCacheMap更新,Eureka client默認(rèn)從這里更新服務(wù)注冊(cè)信息,可配置直接從readWriteCacheMap更新 |
緩存相關(guān)配置
配置 | 默認(rèn) | 說明 |
---|---|---|
eureka.server.useReadOnlyResponseCache | true | Client從readOnlyCacheMap更新數(shù)據(jù),false則跳過readOnlyCacheMap直接從readWriteCacheMap更新 |
eureka.server.responsecCacheUpdateIntervalMs | 30000 | readWriteCacheMap更新至readOnlyCacheMap周期,默認(rèn)30s |
eureka.server.evictionIntervalTimerInMs | 60000 | 清理未續(xù)約節(jié)點(diǎn)(evict)周期,默認(rèn)60s |
eureka.instance.leaseExpirationDurationInSeconds | 90 | 清理未續(xù)約節(jié)點(diǎn)超時(shí)時(shí)間,默認(rèn)90s |
關(guān)鍵類
類名 | 說明 |
---|---|
com.netflix.eureka.registry.AbstractInstanceRegistry | 保存服務(wù)注冊(cè)信息,持有registry和responseCache成員變量 |
com.netflix.eureka.registry.ResponseCacheImpl | 持有readWriteCacheMap和readOnlyCacheMap成員變量 |
Eureka Client存在兩種角色:服務(wù)提供者和服務(wù)消費(fèi)者,作為服務(wù)消費(fèi)者一般配合Ribbon或Feign(Feign內(nèi)部使用Ribbon)使用。Eureka Client啟動(dòng)后,作為服務(wù)提供者立即向Server注冊(cè),默認(rèn)情況下每30s續(xù)約(renew);作為服務(wù)消費(fèi)者立即向Server全量更新服務(wù)注冊(cè)信息,默認(rèn)情況下每30s增量更新服務(wù)注冊(cè)信息;Ribbon延時(shí)1s向Client獲取使用的服務(wù)注冊(cè)信息,默認(rèn)每30s更新使用的服務(wù)注冊(cè)信息,只保存狀態(tài)為UP的服務(wù)。
二級(jí)緩存
緩存 | 類型 | 說明 |
---|---|---|
localRegionApps | AtomicReference | 周期更新,類DiscoveryClient成員變量,Eureka Client保存服務(wù)注冊(cè)信息,啟動(dòng)后立即向Server全量更新,默認(rèn)每30s增量更新 |
upServerListZoneMap | ConcurrentHashMap | 周期更新,類LoadBalancerStats成員變量,Ribbon保存使用且狀態(tài)為UP的服務(wù)注冊(cè)信息,啟動(dòng)后延時(shí)1s向Client更新,默認(rèn)每30s更新 |
緩存相關(guān)配置
配置 | 默認(rèn) | 說明 |
---|---|---|
eureka.instance.leaseRenewalIntervalInSeconds | 30 | Eureka Client 續(xù)約周期,默認(rèn)30s |
eureka.client.registryFetchIntervalSeconds | 30 | Eureka Client 增量更新周期,默認(rèn)30s(正常情況下增量更新,超時(shí)或與Server端不一致等情況則全量更新) |
ribbon.ServerListRefreshInterval | 30000 | Ribbon 更新周期,默認(rèn)30s |
關(guān)鍵類
類名 | 說明 |
---|---|
com.netflix.discovery.DiscoveryClient | Eureka Client 負(fù)責(zé)注冊(cè)、續(xù)約和更新,方法initScheduledTasks()分別初始化續(xù)約和更新定時(shí)任務(wù) |
com.netflix.loadbalancer.PollingServerListUpdater | Ribbon 更新使用的服務(wù)注冊(cè)信息,start初始化更新定時(shí)任務(wù) |
com.netflix.loadbalancer.LoadBalancerStats | Ribbon,保存使用且狀態(tài)為UP的服務(wù)注冊(cè)信息 |
Eureka Client | 時(shí)間 | 說明 |
---|---|---|
上線 | 30(readOnly)+30(Client)+30(Ribbon)=90s | readWrite -> readOnly -> Client -> Ribbon 各30s |
正常下線 | 30(readonly)+30(Client)+30(Ribbon)=90s | 服務(wù)正常下線(kill或kill -15殺死進(jìn)程)會(huì)給進(jìn)程善后機(jī)會(huì),DiscoveryClient.shutdown()將向Server更新自身狀態(tài)為DOWN,然后發(fā)送DELETE請(qǐng)求注銷自己,registry和readWriteCacheMap實(shí)時(shí)更新,故UI將不再顯示該服務(wù)實(shí)例 |
非正常下線 | 30+60(evict)*2+30+30+30= 240s | 服務(wù)非正常下線(kill -9殺死進(jìn)程或進(jìn)程崩潰)不會(huì)觸發(fā)DiscoveryClient.shutdown()方法,Eureka Server將依賴每60s清理超過90s未續(xù)約服務(wù)從registry和readWriteCacheMap中刪除該服務(wù)實(shí)例 |
考慮如下情況
0s時(shí)服務(wù)未通知Eureka Client直接下線;
29s時(shí)第一次過期檢查evict未超過90s;
89s時(shí)第二次過期檢查evict未超過90s;
149s時(shí)第三次過期檢查evict未續(xù)約時(shí)間超過了90s,故將該服務(wù)實(shí)例從registry和readWriteCacheMap中刪除;
179s時(shí)定時(shí)任務(wù)從readWriteCacheMap更新至readOnlyCacheMap;
209s時(shí)Eureka Client從Eureka Server的readOnlyCacheMap更新;
239s時(shí)Ribbon從Eureka Client更新。
因此,極限情況下服務(wù)消費(fèi)者最長(zhǎng)感知時(shí)間將無限趨近240s。
六、應(yīng)對(duì)措施服務(wù)注冊(cè)中心在選擇使用Eureka時(shí)說明已經(jīng)接受了其優(yōu)先保證可用性(A)和分區(qū)容錯(cuò)性(P)、不保證強(qiáng)一致性(C)的特點(diǎn)。如果需要優(yōu)先保證強(qiáng)一致性(C),則應(yīng)該考慮使用ZooKeeper等CP系統(tǒng)作為服務(wù)注冊(cè)中心。分布式系統(tǒng)中一般配置多節(jié)點(diǎn),單個(gè)節(jié)點(diǎn)服務(wù)上線的狀態(tài)更新滯后并沒有什么影響,這里主要考慮服務(wù)下線后狀態(tài)更新滯后的應(yīng)對(duì)措施。
6.1 Eureka Server
1.縮短readOnlyCacheMap更新周期。縮短該定時(shí)任務(wù)周期可減少滯后時(shí)間。
eureka.server.responsecCacheUpdateIntervalMs: 10000 # Eureka Server readOnlyCacheMap更新周期
2.關(guān)閉readOnlyCacheMap。中小型系統(tǒng)可以考慮該方案,Eureka Client直接從readWriteCacheMap更新服務(wù)注冊(cè)信息。
eureka.server.useReadOnlyResponseCache: false # 是否使用readOnlyCacheMap6.2 Eureka Client
1.服務(wù)消費(fèi)者使用容錯(cuò)機(jī)制。如Spring Cloud Retry和Hystrix,Ribbon、Feign、Zuul都可以配置Retry,服務(wù)消費(fèi)者訪問某個(gè)已下線節(jié)點(diǎn)時(shí)一般報(bào)ConnectTimeout,這時(shí)可以通過Retry機(jī)制重試下一個(gè)節(jié)點(diǎn)。
2.服務(wù)消費(fèi)者縮短更新周期。Eureka Client和Ribbon二級(jí)緩存影響狀態(tài)更新,縮短這兩個(gè)定時(shí)任務(wù)周期可減少滯后時(shí)間,例如配置:
eureka.client.registryFetchIntervalSeconds: 5 # Eureka Client更新周期 ribbon.ServerListRefreshInterval: 2000 # Ribbon更新周期
3.服務(wù)提供者保證服務(wù)正常下線。服務(wù)下線時(shí)使用kill或kill -15命令,避免使用kill -9命令,kill或kill -15命令殺死進(jìn)程時(shí)將觸發(fā)Eureka Client的shutdown()方法,主動(dòng)刪除Server的registry和readWriteCacheMap中的注冊(cè)信息,不必依賴Server的evict清除。
4.服務(wù)提供者延遲下線。服務(wù)下線之前先調(diào)用接口使Eureka Server中保存的服務(wù)狀態(tài)為DOWN或OUT_OF_SERVICE后再下線,二者時(shí)間差根據(jù)緩存機(jī)制和配置決定,比如默認(rèn)情況下調(diào)用接口后延遲90s再下線服務(wù)即可保證服務(wù)消費(fèi)者不會(huì)調(diào)用已下線服務(wù)實(shí)例。
七、網(wǎng)關(guān)實(shí)現(xiàn)服務(wù)下線實(shí)時(shí)感知在軟件工程中,沒有一個(gè)問題是中間層解決不了的,而網(wǎng)關(guān)是服務(wù)提供者和服務(wù)消費(fèi)者的中間層。以Spring Cloud Zuul網(wǎng)關(guān)為例,網(wǎng)關(guān)作為Eureka Client保存了服務(wù)注冊(cè)信息,服務(wù)消費(fèi)者通過網(wǎng)關(guān)將請(qǐng)求轉(zhuǎn)發(fā)給服務(wù)提供者,只需要做到服務(wù)提供者下線時(shí)通知網(wǎng)關(guān)在自己保存的服務(wù)列表中使該服務(wù)失效。為了保持網(wǎng)關(guān)的獨(dú)立性,可實(shí)現(xiàn)一個(gè)獨(dú)立服務(wù)接收下線通知并協(xié)調(diào)網(wǎng)關(guān)集群。下篇文章將詳細(xì)介紹網(wǎng)關(guān)如何實(shí)現(xiàn)服務(wù)下線實(shí)時(shí)感知,敬請(qǐng)期待!
作者:馮永彪
內(nèi)容來源:宜信技術(shù)學(xué)院
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/62108.html
摘要:服務(wù)提供者的運(yùn)行機(jī)制用了雙層結(jié)構(gòu)來維護(hù)注冊(cè)的服務(wù)信息,第一層為服務(wù)的名稱,第二層為服務(wù)的實(shí)例名稱。服務(wù)注冊(cè)中心的運(yùn)行機(jī)制為了防止服務(wù)的異常下線,會(huì)周期性的清理列表中未續(xù)約的服務(wù)。負(fù)載均衡器的基本功能維護(hù)該服務(wù)下的所有節(jié)點(diǎn)列表。 Spring Boot Spring Boot有什么作用 Spring Boot通過自動(dòng)化的配置簡(jiǎn)化Spring原有的樣板化的配置。 Spring Boo...
摘要:是一個(gè)相對(duì)比較新的微服務(wù)框架,年才推出的版本雖然時(shí)間最短但是相比等框架提供的全套的分布式系統(tǒng)解決方案。提供線程池不同的服務(wù)走不同的線程池,實(shí)現(xiàn)了不同服務(wù)調(diào)用的隔離,避免了服務(wù)器雪崩的問題。通過互相注冊(cè)的方式來進(jìn)行消息同步和保證高可用。 Spring Cloud 是一個(gè)相對(duì)比較新的微服務(wù)框架,...
摘要:今天整理了一下近大半年以來的一些文章,和我的預(yù)期一樣,很多文章我都忘記自己曾經(jīng)寫過了,這個(gè)記錄的過程讓我也有了新的理解。希望大家,收藏,點(diǎn)贊,加轉(zhuǎn)發(fā)。 今天整理了一下近大半年以來的一些文章,和我的預(yù)期一樣,很多文章我都忘記自己曾經(jīng)寫過了,這個(gè)記錄的過程讓我也有了新的理解。希望大家,收藏,點(diǎn)贊,加轉(zhuǎn)發(fā)。 面試必備 面試必備:深入Spring MVC DispatchServlet 源碼...
摘要:今天整理了一下近大半年以來的一些文章,和我的預(yù)期一樣,很多文章我都忘記自己曾經(jīng)寫過了,這個(gè)記錄的過程讓我也有了新的理解。希望大家,收藏,點(diǎn)贊,加轉(zhuǎn)發(fā)。 今天整理了一下近大半年以來的一些文章,和我的預(yù)期一樣,很多文章我都忘記自己曾經(jīng)寫過了,這個(gè)記錄的過程讓我也有了新的理解。希望大家,收藏,點(diǎn)贊,加轉(zhuǎn)發(fā)。 面試必備 面試必備:深入Spring MVC DispatchServlet 源碼...
摘要:圖解的緩存架構(gòu)干貨盤點(diǎn)悟空聊架構(gòu)默認(rèn)會(huì)先從只讀緩存里面找。圖解的緩存架構(gòu)干貨盤點(diǎn)緩存讀寫緩存過期的時(shí)候其實(shí)分兩種定時(shí)過期和實(shí)時(shí)過期。 大家好,我是悟空。先說下哈,這篇文章畫原理圖用了很多時(shí)間,求個(gè)三連!Eureka 注冊(cè)中心系列文章已經(jīng)寫到第七篇了,這里匯總下:??領(lǐng)導(dǎo)讓我研究 Eureka 源碼 | 啟動(dòng)過程????領(lǐng)導(dǎo)...
閱讀 3529·2021-09-27 13:35
閱讀 3567·2019-08-29 17:09
閱讀 2438·2019-08-26 11:30
閱讀 709·2019-08-26 10:32
閱讀 540·2019-08-26 10:23
閱讀 1202·2019-08-26 10:20
閱讀 3159·2019-08-23 15:26
閱讀 3565·2019-08-23 14:33