一、eureka概述
1、背景
(1)netflix公司與AWS的ELB
- netflix是世界上最大的流媒體視頻網(wǎng)站,其公司的架構(gòu)師基于AWS云開發(fā)的。在AWS中使用的負(fù)載均衡器是ELB(Elastic Load Balancing),即彈性負(fù)載均衡通過流量分發(fā)擴(kuò)展應(yīng)用系統(tǒng)對(duì)外的服務(wù)能力(類似阿里云SLB服務(wù))。理論上是可以通過ELB對(duì)內(nèi)部進(jìn)行負(fù)載均衡的,但是如果這樣就會(huì)暴露到外網(wǎng),存在安全性問題;另外ELB是基于傳統(tǒng)的代理的負(fù)載均衡解決方案,無法直接基于服務(wù)元數(shù)據(jù)信息定義負(fù)載均衡算法。也就是說使用ELB有一定的限制,無法根據(jù)復(fù)雜的生產(chǎn)環(huán)境提供更為復(fù)雜的負(fù)載均衡方案,且存在一定的安全隱患。
(2)eureka誕生
- netflix鑒于自己的生產(chǎn)環(huán)境,設(shè)計(jì)出了eureka,一方面給內(nèi)部服務(wù)做服務(wù)發(fā)現(xiàn),另一方面可以結(jié)合ribbon組件提供各種個(gè)性化的負(fù)載均衡算法。ELB亦是傳統(tǒng)的基于代理實(shí)現(xiàn)的負(fù)載均衡解決方案而Eureka則與之不同,Eureka屬于客戶端發(fā)現(xiàn)模式,客戶端負(fù)責(zé)決定相應(yīng)服務(wù)實(shí)例的網(wǎng)絡(luò)位置,并且對(duì)請(qǐng)求實(shí)現(xiàn)負(fù)載均衡??蛻舳藦囊粋€(gè)服務(wù)注冊(cè)服務(wù)中查詢所有可用服務(wù)實(shí)例的庫(kù),并緩存到本地。
(3)ELB和eureka搭配使用
-
在生產(chǎn)中如果是使用AWS等云服務(wù),可以結(jié)合eureka一起使用(以AWS為例),ELB用來對(duì)客戶端或者終端設(shè)備進(jìn)行請(qǐng)求負(fù)載均衡,而eureka用來對(duì)中間層的服務(wù)做服務(wù)發(fā)現(xiàn),配合其他組件提供負(fù)載均衡的能力。
使用eureka作為中間負(fù)載均衡和服務(wù)發(fā)現(xiàn)
2、eureka優(yōu)勢(shì)
(1)提供完成的服務(wù)注冊(cè)和服務(wù)發(fā)現(xiàn)實(shí)現(xiàn)
- 首先是提供了完整的服務(wù)注冊(cè)和服務(wù)發(fā)現(xiàn)實(shí)現(xiàn),并且也經(jīng)受住了Netflix自己的生產(chǎn)環(huán)境考驗(yàn),相對(duì)使用起來會(huì)比較省心。
(2)與spirngcloud無縫集成
- 我們的項(xiàng)目本身就使用了Spring Cloud和Spring Boot,同時(shí)Spring Cloud還有一套非常完善的開源代碼來整合Eureka,所以使用起來非常方便。另外,Eureka還支持在我們應(yīng)用自身的容器中啟動(dòng),也就是說我們的應(yīng)用啟動(dòng)完之后,既充當(dāng)了Eureka的角色,同時(shí)也是服務(wù)的提供者。這樣就極大的提高了服務(wù)的可用性
(3)采用AP而非CP
- eureka是在部署AWS的背景下面設(shè)計(jì)的,其設(shè)計(jì)認(rèn)為,在云端,特別是大規(guī)模部署情況下面,失敗是不可以避免的,可能是因?yàn)閑ureka自身部署失敗或者網(wǎng)絡(luò)分區(qū)等情況導(dǎo)致服務(wù)不可用,這些問題是不可以避免的,要解決這個(gè)問題就需要eureka在網(wǎng)絡(luò)分區(qū)的時(shí)候,還能夠正常提供服務(wù),因此eureka選擇滿足availability這個(gè)特性。
在生產(chǎn)實(shí)踐中,服務(wù)注冊(cè)及發(fā)現(xiàn)中保留可用以及過期的數(shù)據(jù)總比丟失可用的數(shù)據(jù)好。---peter kelly
- eureka選擇了A也就必須放棄C,也就是說在eureka中采用最終一致性的方式來保證數(shù)據(jù)的一致性問題,因此實(shí)例的注冊(cè)信息在集群的所有節(jié)點(diǎn)之間的數(shù)據(jù)都不是強(qiáng)一性的,需要客戶端能支持負(fù)載均衡算法及失敗重試等機(jī)制。
(4)開源
- 代碼是開源的,所以非常便于我們了解它的實(shí)現(xiàn)原理和排查問題。需要的話還可以在上面進(jìn)行二次開發(fā)。
3、eureka和zk作為注冊(cè)中心比較

| 比較項(xiàng)目 | zk | eureka |
|---|---|---|
| 設(shè)計(jì)原則 | CP | AP |
| 優(yōu)點(diǎn) | 數(shù)據(jù)強(qiáng)一致 | 服務(wù)高可用 |
| 缺點(diǎn) | 網(wǎng)絡(luò)分區(qū)會(huì)影響 Leader 選舉,超過閾值后集群不可用 | 服務(wù)節(jié)點(diǎn)間的數(shù)據(jù)可能不一致; Client-Server 間的數(shù)據(jù)可能不一致; |
| 使用場(chǎng)景 | 單機(jī)房集群,對(duì)數(shù)據(jù)一致性要求較高 | 云機(jī)房集群,跨越多機(jī)房部署;對(duì)注冊(cè)中心服務(wù)可用性要求較高 |
二、eureka架構(gòu)設(shè)計(jì)

1、設(shè)計(jì)理念
(1)AP由于CP
(2)Peer to Peer設(shè)計(jì)
- 一般而言在分布式系統(tǒng)的數(shù)據(jù)有多個(gè)副本之間的復(fù)制方式,可以分為主從復(fù)制和對(duì)等復(fù)制
主從復(fù)制:Master-Slave模式,一個(gè)主副本和多個(gè)從副本,所有數(shù)據(jù)的寫操作都是提交到主副本,最后由主副本更新到其他的從副本(常采用異步更新),通常寫是整個(gè)系統(tǒng)的瓶頸所在。
對(duì)等復(fù)制:副本之間不分主從,任何的副本都可以接受寫數(shù)據(jù),然后副本之間進(jìn)行數(shù)據(jù)更新。在對(duì)等復(fù)制中,由于每一個(gè)副本都可以進(jìn)行寫操作,各個(gè)副本之間的數(shù)據(jù)同步及沖突處理是一個(gè)比較難解決的問題。
- eureka中的對(duì)等復(fù)制機(jī)制
1、客戶端:在客戶端中配置相應(yīng)的服務(wù)端的多個(gè)peer節(jié)點(diǎn),在客戶端實(shí)際操作中有如下幾點(diǎn)規(guī)律;(1)有多個(gè)分區(qū)時(shí)候,優(yōu)先選擇與應(yīng)用實(shí)例所在分區(qū)一樣的其他服務(wù)實(shí)例,如果沒有的話選擇默認(rèn)是defaultZone(2)客戶端會(huì)維護(hù)一個(gè)可用的server列表,請(qǐng)求的時(shí)候優(yōu)先從可用的列表中進(jìn)行選擇,如果請(qǐng)求失敗切換到下一個(gè)server進(jìn)行重試,重試次數(shù)為3次(3)為了防止客戶端請(qǐng)求服務(wù)端的節(jié)點(diǎn)不均勻現(xiàn)象,客戶端有一個(gè)定時(shí)任務(wù)來刷新并隨機(jī)化eureka server的列表。
2、服務(wù)端:server本身依賴于客戶端,也就是每一個(gè)server是作為其他server的客戶端存在。在一個(gè)server啟動(dòng)的時(shí)候,有一個(gè)synvUp操作,通過客戶端請(qǐng)求其他的server節(jié)點(diǎn)中的一個(gè)節(jié)點(diǎn)獲取注冊(cè)的應(yīng)用實(shí)例信息,然后復(fù)制到其他的peer節(jié)點(diǎn)。eureka中采用版本號(hào)(lastDirtyTimestamp)和心跳機(jī)制(renewLease從新租約方式)的方式來解決數(shù)據(jù)復(fù)制過程中的沖突問題。
(3)Zone和region的設(shè)計(jì)
- 使用region來代表一個(gè)獨(dú)立的地理區(qū)域,比如us-east-1、us-east-2,、us-west-1等。在每一個(gè)region下面還分為多個(gè)AvailabilityZone,一個(gè)region對(duì)應(yīng)多個(gè)AvailabilityZone,不同的region之間相互隔離。默認(rèn)情況下面資源只是在單個(gè)region之間的AvailabilityZone之間進(jìn)行復(fù)制,跨region之間不會(huì)進(jìn)行資源的復(fù)制。
- AvailabilityZone看成是region下面的一個(gè)一個(gè)機(jī)房,各個(gè)機(jī)房相對(duì)獨(dú)立,主要是為了region的高可用考慮的,一個(gè)region下面的機(jī)房掛了,還有其他的機(jī)房可以使用。
- 一個(gè)AvailabilityZone可以設(shè)置多個(gè)server實(shí)例,他們之間構(gòu)成peer節(jié)點(diǎn),然后采用peer to peer的復(fù)制模式進(jìn)行數(shù)據(jù)復(fù)制。
(4)self preservation設(shè)計(jì)
- 在分布式系統(tǒng)設(shè)計(jì)中,通常需要對(duì)應(yīng)用實(shí)例的存活進(jìn)行健康檢驗(yàn),這里比較難處理的就是網(wǎng)絡(luò)偶爾抖動(dòng)或者短暫不可用而造成的誤判。因此eureka設(shè)計(jì)了self preservation機(jī)制。server和client之間有一個(gè)租約,client定期發(fā)送心跳來維護(hù)這個(gè)租約,表示心跳還活著,eureka通過當(dāng)前注冊(cè)的實(shí)例數(shù)量,去計(jì)算每分鐘應(yīng)用從應(yīng)用實(shí)例接受到的心跳數(shù)量,如果近一分鐘接受到的租約的次數(shù)小于等于指定的閾值,則關(guān)閉租約失效剔除,禁止定時(shí)任務(wù)剔除失效的實(shí)例,從而保護(hù)注冊(cè)信息。
2、組件調(diào)用關(guān)系設(shè)計(jì)
(1)服務(wù)提供者
1、啟動(dòng)后,向注冊(cè)中心發(fā)起 register 請(qǐng)求,注冊(cè)服務(wù)
2、在運(yùn)行過程中,定時(shí)向注冊(cè)中心發(fā)送 renew 心跳,證明“我還活著”。
3、停止服務(wù)提供者,向注冊(cè)中心發(fā)起 cancel 請(qǐng)求,清空當(dāng)前服務(wù)注冊(cè)信息。
(2)服務(wù)消費(fèi)者
1、啟動(dòng)后,從注冊(cè)中心拉取服務(wù)注冊(cè)信息
2、在運(yùn)行過程中,定時(shí)更新服務(wù)注冊(cè)信息。
3、服務(wù)消費(fèi)者發(fā)起遠(yuǎn)程調(diào)用:
a> 服務(wù)消費(fèi)者(北京)會(huì)從服務(wù)注冊(cè)信息中選擇同機(jī)房的服務(wù)提供者(北京),發(fā)起遠(yuǎn)程調(diào)用。只有同機(jī)房的服務(wù)提供者掛了才會(huì)選擇其他機(jī)房的服務(wù)提供者(青島)。
b> 服務(wù)消費(fèi)者(天津)因?yàn)橥瑱C(jī)房?jī)?nèi)沒有服務(wù)提供者,則會(huì)按負(fù)載均衡算法選擇北京或青島的服務(wù)提供者,發(fā)起遠(yuǎn)程調(diào)用。
(3)服務(wù)注冊(cè)中心
1、啟動(dòng)后,從其他節(jié)點(diǎn)拉取服務(wù)注冊(cè)信息。
2、運(yùn)行過程中,定時(shí)運(yùn)行 evict 任務(wù),剔除沒有按時(shí) renew 的服務(wù)(包括非正常停止和網(wǎng)絡(luò)故障的服務(wù))。
3、運(yùn)行過程中,接收到的 register、renew、cancel 請(qǐng)求,都會(huì)同步至其他注冊(cè)中心節(jié)點(diǎn)
3、數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)

- Eureka 的數(shù)據(jù)存儲(chǔ)分了兩層:數(shù)據(jù)存儲(chǔ)層和緩存層。
Eureka Client 在拉取服務(wù)信息時(shí),先從緩存層獲?。ㄏ喈?dāng)于 Redis),如果獲取不到,先把數(shù)據(jù)存儲(chǔ)層的數(shù)據(jù)加載到緩存中(相當(dāng)于 Mysql),再?gòu)木彺嬷蝎@取。值得注意的是,數(shù)據(jù)存儲(chǔ)層的數(shù)據(jù)結(jié)構(gòu)是服務(wù)信息,而緩存中保存的是經(jīng)過處理加工過的、可以直接傳輸?shù)?Eureka Client 的數(shù)據(jù)結(jié)構(gòu)。
(1)數(shù)據(jù)存儲(chǔ)層
第一層的 key 是spring.application.name,value 是第二層 ConcurrentHashMap;
第二層 ConcurrentHashMap 的 key 是服務(wù)的 InstanceId,value 是 Lease 對(duì)象;
Lease 對(duì)象包含了服務(wù)詳情和服務(wù)治理相關(guān)的屬性。
- 更新一級(jí)緩存:
Eureka Server 內(nèi)置了一個(gè) TimerTask,定時(shí)將二級(jí)緩存中的數(shù)據(jù)同步到一級(jí)緩存(這個(gè)動(dòng)作包括了刪除和加載)。
(2)二級(jí)緩存層
一級(jí)緩存:ConcurrentHashMap<Key,Value> readOnlyCacheMap,本質(zhì)上是 HashMap,無過期時(shí)間,保存服務(wù)信息的對(duì)外輸出數(shù)據(jù)結(jié)構(gòu)。
二級(jí)緩存:Loading<Key,Value> readWriteCacheMap,本質(zhì)上是 guava 的緩存,包含失效機(jī)制,保存服務(wù)信息的對(duì)外輸出數(shù)據(jù)結(jié)構(gòu)。
-
二級(jí)緩存的更新機(jī)制:
eureka二級(jí)緩存的更新機(jī)制 - 刪除二級(jí)緩存:
1、Eureka Client 發(fā)送 register、renew 和 cancel 請(qǐng)求并更新 registry 注冊(cè)表之后,刪除二級(jí)緩存;2、Eureka Server 自身的 Evict Task 剔除服務(wù)后,刪除二級(jí)緩存;3、二級(jí)緩存本身設(shè)置了 guava 的失效機(jī)制,隔一段時(shí)間后自己自動(dòng)失效;
- 加載二級(jí)緩存:
1、Eureka Client 發(fā)送 getRegistry 請(qǐng)求后,如果二級(jí)緩存中沒有,就觸發(fā) guava 的 load,即從 registry 中獲取原始服務(wù)信息后進(jìn)行處理加工,再加載到二級(jí)緩存中。
2、Eureka Server 更新一級(jí)緩存的時(shí)候,如果二級(jí)緩存沒有數(shù)據(jù),也會(huì)觸發(fā) guava 的 load。
- 重點(diǎn)關(guān)注:ResponseCacheImpl類
三、eureka高可用原理分析
- 前面講了eureka是基于AWS開發(fā)出來的框架,因此eureka天生的支持region和availabilityZone的概念。
1、默認(rèn)情況下面不同region是相互隔離的,region之間的數(shù)據(jù)是不會(huì)復(fù)制的,但是eureka client提供了fetch-remote-regions-registry配置,作用是拉取遠(yuǎn)程的注冊(cè)信息到本地
2、availabilityZone,eureka中默認(rèn)eureka-client-prefer-zone-eureka配置為true,也就是拉取serverUrl時(shí)候,默認(rèn)選取和應(yīng)用實(shí)例同一個(gè)zone的eureka server列表。
1、客戶端高可用原理
(1)在client啟動(dòng)之前,如果沒有eureka server,則通過配置eureka.client.back-registry-impl從備份的registry讀取關(guān)鍵服務(wù)的信息。
(2)在client啟動(dòng)后,如果運(yùn)行時(shí)候server全部掛掉了,本地內(nèi)存有l(wèi)ocalRegion之前獲取的數(shù)據(jù)。
(3)如果是server部分掛了。如果預(yù)計(jì)恢復(fù)時(shí)間比較長(zhǎng),可以人工介入,通過配置中心人工摘除服務(wù)(但是基本不用這樣做)。在client中會(huì)維護(hù)一份不可用的server列表,一旦心跳時(shí)候失敗,當(dāng)該列表的大小超過指定的閾值時(shí)候就會(huì)進(jìn)行重新清空,重新清空后,client會(huì)進(jìn)行重試(默認(rèn)3次)
2、服務(wù)端高可用原理
- 服務(wù)端采用peer to peer的架構(gòu)模式,原則上就是高可用的。同時(shí)服務(wù)端還可以通過配置remoteRegionUrlsWithName來支持拉取遠(yuǎn)程的region實(shí)例,如果當(dāng)前的region掛了,會(huì)自動(dòng)fallback到遠(yuǎn)程的region獲取數(shù)據(jù)
- 同時(shí)服務(wù)端采用renew租約和定時(shí)心跳的方式保護(hù)注冊(cè)信息(self preservation機(jī)制)
參考:
微服務(wù)注冊(cè)中心 Eureka 架構(gòu)深入解讀
重新定義springcloud
深度剖析服務(wù)發(fā)現(xiàn)組件Netflix Eureka
其他資料

