Eureka原理學(xué)習(xí)

一、流程圖

Eureka 流程圖
Eureka 流程圖

二、客戶(hù)端Client

  • 服務(wù)啟動(dòng),經(jīng)過(guò)一系列的配置加載(過(guò)程參考)之后會(huì)實(shí)例化DiscoveryClient對(duì)象,在其構(gòu)造方法中創(chuàng)建定時(shí)任務(wù)initScheduledTasks(),進(jìn)行服務(wù)信息列表拉取和服務(wù)續(xù)約(eureka.client.registerWithEureka=true)

服務(wù)續(xù)約(HeartbeatThread):發(fā)送心跳request,請(qǐng)求eureka server 端 ,如果接口返回值為404,就是說(shuō)注冊(cè)中心不存在該服務(wù),則走注冊(cè)流程Registry。默認(rèn)是30s(eureka.instance.lease-renewal-interval-in-seconds)發(fā)送一次心跳
服務(wù)信息拉?。–acheRefreshThread):調(diào)用fetchRegistry(),根據(jù)條件判斷,進(jìn)行全量或增量拉取Eureka服務(wù)端信息并緩存到本地(分別調(diào)用getAndStoreFullRegistry()或getAndUpdateDelta()方法)。默認(rèn)是30s(eureka.client.registry-fetch-interval-seconds)拉取一次服務(wù)注冊(cè)信息

  • 服務(wù)注冊(cè),通過(guò)http rest請(qǐng)求eureka server端,把應(yīng)用自身的InstanceInfo實(shí)例注冊(cè)給server端

InstanceInfo(com.netflix.appinfo.InstanceInfo)核心屬性
1.instanceId:實(shí)例id。在同一個(gè)應(yīng)用appName的范圍內(nèi)是必須是惟一的
2.appName:應(yīng)用名。如USER_SERVER(同一應(yīng)用可以有N多個(gè)實(shí)例)
3.ipAddr:本實(shí)例的ip地址。如ipAddr=192.168.1.100
4.port:端口號(hào)。默認(rèn)值是7001
5.healthCheckUrl:健康檢查的URL(Rest)。如http://localhost:8080/actuator/health
6.leaseInfo:一個(gè)com.netflix.appinfo.LeaseInfo對(duì)象,表示續(xù)約相關(guān)信息
7.metadata:自定義元數(shù)據(jù),可以是任何k-v
8.lastUpdatedTimestamp:上次修改時(shí)間

  • 服務(wù)下線,及時(shí)通知服務(wù)端把自己剔除

調(diào)用cancelScheduledTasks()關(guān)閉各種定時(shí)任務(wù),如續(xù)約、信息拉取等,同時(shí)向Eureka Server端發(fā)送下線請(qǐng)求

三、服務(wù)端Server

  • 服務(wù)啟動(dòng)
    經(jīng)過(guò)一系列的配置加載(過(guò)程參考)之后會(huì)實(shí)例化EurekaServerBootstrap對(duì)象,該對(duì)象初始化方法中會(huì)創(chuàng)建一個(gè)定時(shí)任務(wù)來(lái)更新集群節(jié)點(diǎn)信息

檢測(cè)集群中各個(gè)Server節(jié)點(diǎn)的可用性,進(jìn)行不可用節(jié)點(diǎn)剔除和可用節(jié)點(diǎn)新建。定期更新頻率默認(rèn)值為10分鐘,可以通過(guò)eureka.server.peerEurekaNodesUpdateIntervalMs配置)
集群原理
配置集群必須不同ip
相互之間不區(qū)分主節(jié)點(diǎn)和從節(jié)點(diǎn),所有節(jié)點(diǎn)都是平等,幾個(gè)節(jié)點(diǎn)掛掉不會(huì)影響正常節(jié)點(diǎn)的工作,剩余的節(jié)點(diǎn)依然可以提供注冊(cè)和查詢(xún)服務(wù)
server也是client,所以幾個(gè)server組成集群,要彼此互相注冊(cè)
Client 在向某個(gè) Eureka 注冊(cè)時(shí),如果發(fā)現(xiàn)連接失敗,則會(huì)自動(dòng)切換至其它節(jié)點(diǎn)。只要有一臺(tái) Eureka Server 還在,就能保證注冊(cè)服務(wù)可用(保證可用性),只不過(guò)查到的信息可能不是最新的(不保證強(qiáng)一致性)。從這里可以看出client只會(huì)選擇一個(gè)server進(jìn)行注冊(cè),注冊(cè)后由server根據(jù)配置中集群的信息用同樣的方式注冊(cè)到其他server上。
Client啟動(dòng)后注冊(cè)一個(gè)server,之后如果這個(gè)Eureka Server掛了,才會(huì)切換Eureka Server,在當(dāng)前使用的Eureka Server掛掉之前,不會(huì)切換

調(diào)用EurekaServerBootstrap類(lèi)的contextInitialized()方法進(jìn)行Eureka服務(wù)的初始化

初始化Eureka的環(huán)境變量(initEurekaEnvironment)
初始化Eureka的上下文(initEurekaServerContext),包括集群中同步相鄰節(jié)點(diǎn)上的注冊(cè)信息,開(kāi)啟一個(gè)定時(shí)任務(wù),將沒(méi)有續(xù)約的客戶(hù)端服務(wù)實(shí)例(默認(rèn)90秒沒(méi)有續(xù)約ureka.instance.lease-expiration-duration-in-seconds)清理掉

  • 服務(wù)注冊(cè)
    Eureka注冊(cè)中心有一個(gè)Map來(lái)保存所有的服務(wù)及映射的機(jī)器信息:
private final ConcurrentHashMap<String, Map<String, Lease<InstanceInfo>>> registry   = new ConcurrentHashMap<String, Map<String, Lease<InstanceInfo>>>();
  1. 服務(wù)注冊(cè)時(shí),會(huì)把服務(wù)的信息寫(xiě)到這個(gè)registry中
  2. 服務(wù)從治理中心拉取服務(wù)列表信息時(shí),不會(huì)從這個(gè)registry中拉取,而是從一個(gè)ResponseCache中拉取,這樣讀寫(xiě)分離的原因應(yīng)該是為了支持高并發(fā)。
    為了提高Eureka Server注冊(cè)中心的性能,Eureka Server提供了二級(jí)緩存機(jī)制,將服務(wù)注冊(cè)信息保存在二級(jí)緩存中(eureka.server.shouldUseReadOnlyResponseCache = true)。
    第一層緩存:readOnlyCacheMap,數(shù)據(jù)是從ReadWriteMap來(lái)的,當(dāng)服務(wù)需要獲取服務(wù)列表是,會(huì)直接取這個(gè)ReadOnlyMap的數(shù)據(jù),當(dāng)這個(gè)數(shù)據(jù)不存在時(shí),才會(huì)從ReadWriteMap中更新。
    第二層緩存:readWriteCacheMap,數(shù)據(jù)是從registry中來(lái)的,可以認(rèn)為是registry的緩存,當(dāng)服務(wù)注冊(cè)時(shí),除了把信息寫(xiě)到registry中外,還會(huì)讓ReadWriteMap主動(dòng)過(guò)期,使得會(huì)去從registry重新拉取數(shù)據(jù)
    ReadWriteMap與registry的數(shù)據(jù)是實(shí)時(shí)一致的,但是ReadWriteMap與ReadOnlyMap不是實(shí)時(shí)一致的,而是通過(guò)TimerTask定時(shí)(eureka.server.responsecCacheUpdateIntervalMs,默認(rèn)30S)將readWriteCacheMap同步到readOnlyCacheMap
  • 數(shù)據(jù)同步
    當(dāng)我們啟動(dòng)一個(gè)客戶(hù)端時(shí),會(huì)調(diào)用PeerAwareInstanceRegistryImpl.register() 進(jìn)行服務(wù)的注冊(cè),并調(diào)用replicateToPeers()方法復(fù)制給其他節(jié)點(diǎn)
    當(dāng)我關(guān)閉客戶(hù)端服務(wù)時(shí),則會(huì)進(jìn)入cancel() 方法,進(jìn)行服務(wù)的關(guān)閉,同時(shí)進(jìn)行服務(wù)狀態(tài)列表的更新以及各節(jié)點(diǎn)的注冊(cè)信息同步

通過(guò)互相同步數(shù)據(jù)來(lái)做到數(shù)據(jù)同步,異步同步,達(dá)到最終一致。
當(dāng)自己的節(jié)點(diǎn)發(fā)生變化就會(huì)同步,A-B-C同步過(guò)程如下:
如果client注冊(cè)到A,A的節(jié)點(diǎn)就發(fā)生了變化,A會(huì)同步(這里不是像數(shù)據(jù)庫(kù)一樣的通過(guò)log之類(lèi)的做同步,而是A中的client通過(guò)相同的方式注冊(cè)到B和C)到B和C,此時(shí)B、C的節(jié)點(diǎn)也變化了,但是是因?yàn)锳同步過(guò)來(lái)導(dǎo)致的變化,所以B、C不會(huì)再同步給其他
區(qū)別:Client-A: Header信息中isReplication=true, A-BC: isReplication=false,防止循環(huán)復(fù)制

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容