Spring Cloud分布式微服務(wù)云架構(gòu)源碼分析 — Eureka

在看具體源碼前肢簿,我們先回顧一下之前我們所實(shí)現(xiàn)的內(nèi)容,從而找一個合適的切入口去分析深浮。首先压怠,服務(wù)注冊中心、服務(wù)提供者飞苇、服務(wù)消費(fèi)者這三個主要元素來說菌瘫,后兩者(也就是Eureka客戶端)在整個運(yùn)行機(jī)制中是大部分通信行為的主動發(fā)起者蜗顽,而注冊中心主要是處理請求的接收者。所以雨让,我們可以從Eureka的客戶端作為入口看看它是如何完成這些主動通信行為的雇盖。

我們在將一個普通的Spring Boot應(yīng)用注冊到Eureka Server中,或是從Eureka Server中獲取服務(wù)列表時栖忠,主要就做了兩件事:

在應(yīng)用主類中配置了@EnableDiscoveryClient注解

在application.properties中用eureka.client.serviceUrl.defaultZone參數(shù)指定了服務(wù)注冊中心的位置

順著上面的線索崔挖,我們先查看@EnableDiscoveryClient的源碼如下:

/**

* Annotation to enable a DiscoveryClient implementation.

*@authorSpencer Gibb

*/

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Inherited

@Import(EnableDiscoveryClientImportSelector.class)

public@interfaceEnableDiscoveryClient {

}

從該注解的注釋我們可以知道:該注解用來開啟DiscoveryClient的實(shí)例。通過搜索DiscoveryClient庵寞,我們可以發(fā)現(xiàn)有一個類和一個接口虚汛。通過梳理可以得到如下圖的關(guān)系:

其中,左邊的org.springframework.cloud.client.discovery.DiscoveryClient是Spring Cloud的接口皇帮,它定義了用來發(fā)現(xiàn)服務(wù)的常用抽象方法,而org.springframework.cloud.netflix.eureka.EurekaDiscoveryClient是對該接口的實(shí)現(xiàn)蛋辈,從命名來就可以判斷属拾,它實(shí)現(xiàn)的是對Eureka發(fā)現(xiàn)服務(wù)的封裝。所以EurekaDiscoveryClient依賴了Eureka的com.netflix.discovery.EurekaClient接口冷溶,EurekaClient繼承了LookupService接口渐白,他們都是Netflix開源包中的內(nèi)容,它主要定義了針對Eureka的發(fā)現(xiàn)服務(wù)的抽象方法逞频,而真正實(shí)現(xiàn)發(fā)現(xiàn)服務(wù)的則是Netflix包中的com.netflix.discovery.DiscoveryClient類纯衍。

那么,我們就看看來詳細(xì)看看DiscoveryClient類苗胀。先解讀一下該類頭部的注釋有個總體的了解襟诸,注釋的大致內(nèi)容如下:

這個類用于幫助與Eureka Server互相協(xié)作。

Eureka Client負(fù)責(zé)了下面的任務(wù):

- 向Eureka Server注冊服務(wù)實(shí)例

- 向Eureka Server為租約續(xù)期

- 當(dāng)服務(wù)關(guān)閉期間基协,向Eureka Server取消租約

- 查詢Eureka Server中的服務(wù)實(shí)例列表

Eureka Client還需要配置一個Eureka Server的URL列表歌亲。

在具體研究Eureka Client具體負(fù)責(zé)的任務(wù)之前,我們先看看對Eureka Server的URL列表配置在哪里澜驮。根據(jù)我們配置的屬性名:eureka.client.serviceUrl.defaultZone陷揪,通過serviceUrl我們找到該屬性相關(guān)的加載屬性,但是在SR5版本中它們都被@Deprecated標(biāo)注了杂穷,并在注視中可以看到@link到了替代類com.netflix.discovery.endpoint.EndpointUtils悍缠,我們可以在該類中找到下面這個函數(shù):

publicstaticMap> getServiceUrlsMapFromConfig(

EurekaClientConfig clientConfig, String instanceZone,booleanpreferSameZone) {

Map> orderedUrls =newLinkedHashMap<>();

String region = getRegion(clientConfig);

String[] availZones = clientConfig.getAvailabilityZones(clientConfig.getRegion());

if(availZones ==null|| availZones.length ==0) {

availZones =newString[1];

availZones[0] = DEFAULT_ZONE;

}

……

intmyZoneOffset = getZoneOffset(instanceZone, preferSameZone, availZones);

String zone = availZones[myZoneOffset];

List serviceUrls = clientConfig.getEurekaServerServiceUrls(zone);

if(serviceUrls !=null) {

orderedUrls.put(zone, serviceUrls);

}

……

returnorderedUrls;

}

Region、Zone

在上面的函數(shù)中耐量,我們可以發(fā)現(xiàn)客戶端依次加載了兩個內(nèi)容飞蚓,第一個是Region,第二個是Zone廊蜒,從其加載邏上我們可以判斷他們之間的關(guān)系:

通過getRegion函數(shù)玷坠,我們可以看到它從配置中讀取了一個Region返回蜗搔,所以一個微服務(wù)應(yīng)用只可以屬于一個Region,如果不特別配置八堡,就默認(rèn)為default樟凄。若我們要自己設(shè)置,可以通過eureka.client.region屬性來定義兄渺。

publicstaticStringgetRegion(EurekaClientConfig clientConfig){

String region = clientConfig.getRegion();

if(region ==null) {

region = DEFAULT_REGION;

}

region = region.trim().toLowerCase();

returnregion;

}

通過getAvailabilityZones函數(shù)缝龄,我們可以知道當(dāng)我們沒有特別為Region配置Zone的時候,將默認(rèn)采用defaultZone挂谍,這也是我們之前配置參數(shù)eureka.client.serviceUrl.defaultZone的由來叔壤。若要為應(yīng)用指定Zone,我們可以通過eureka.client.availability-zones屬性來進(jìn)行設(shè)置口叙。從該函數(shù)的return內(nèi)容炼绘,我們可以Zone是可以有多個的,并且通過逗號分隔來配置妄田。由此俺亮,我們可以判斷Region與Zone是一對多的關(guān)系。

publicString[] getAvailabilityZones(String region) {

String value =this.availabilityZones.get(region);

if(value ==null) {

value = DEFAULT_ZONE;

}

returnvalue.split(",");

}

ServiceUrls

在獲取了Region和Zone信息之后疟呐,才開始真正加載Eureka Server的具體地址脚曾。它根據(jù)傳入的參數(shù)按一定算法確定加載位于哪一個Zone配置的serviceUrls。

intmyZoneOffset = getZoneOffset(instanceZone, preferSameZone, availZones);

String zone = availZones[myZoneOffset];

List serviceUrls = clientConfig.getEurekaServerServiceUrls(zone);

具體獲取serviceUrls的實(shí)現(xiàn)启具,我們可以詳細(xì)查看getEurekaServerServiceUrls函數(shù)的具體實(shí)現(xiàn)類EurekaClientConfigBean本讥,該類是EurekaClientConfig和EurekaConstants接口的實(shí)現(xiàn),用來加載配置文件中的內(nèi)容鲁冯,這里有非常多有用的信息拷沸,這里我們先說一下此處我們關(guān)心的,關(guān)于defaultZone的信息薯演。通過搜索defaultZone堵漱,我們可以很容易的找到下面這個函數(shù),它具體實(shí)現(xiàn)了涣仿,如何解析該參數(shù)的過程勤庐,通過此內(nèi)容,我們就可以知道好港,eureka.client.serviceUrl.defaultZone屬性可以配置多個愉镰,并且需要通過逗號分隔。

publicListgetEurekaServerServiceUrls(String myZone){

String serviceUrls =this.serviceUrl.get(myZone);

if(serviceUrls ==null|| serviceUrls.isEmpty()) {

serviceUrls =this.serviceUrl.get(DEFAULT_ZONE);

}

if(!StringUtils.isEmpty(serviceUrls)) {

finalString[] serviceUrlsSplit = StringUtils.commaDelimitedListToStringArray(serviceUrls);

List eurekaServiceUrls =newArrayList<>(serviceUrlsSplit.length);

for(String eurekaServiceUrl : serviceUrlsSplit) {

if(!endsWithSlash(eurekaServiceUrl)) {

eurekaServiceUrl +="/";

}

eurekaServiceUrls.add(eurekaServiceUrl);

}

returneurekaServiceUrls;

}

returnnewArrayList<>();

}

當(dāng)客戶端在服務(wù)列表中選擇實(shí)例進(jìn)行訪問時钧汹,對于Zone和Region遵循這樣的規(guī)則:優(yōu)先訪問同自己一個Zone中的實(shí)例丈探,其次才訪問其他Zone中的實(shí)例。通過Region和Zone的兩層級別定義拔莱,配合實(shí)際部署的物理結(jié)構(gòu)碗降,我們就可以有效的設(shè)計出區(qū)域性故障的容錯集群隘竭。

從現(xiàn)在開始,我這邊會將近期研發(fā)的springcloud微服務(wù)云架構(gòu)的搭建過程和精髓記錄下來讼渊,幫助更多有興趣研發(fā)spring cloud框架的朋友动看,希望可以幫助更多的好學(xué)者。大家來一起探討spring cloud架構(gòu)的搭建過程及如何運(yùn)用于企業(yè)項目爪幻。源碼來源

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末菱皆,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子挨稿,更是在濱河造成了極大的恐慌仇轻,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件奶甘,死亡現(xiàn)場離奇詭異篷店,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)臭家,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進(jìn)店門疲陕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人侣监,你說我怎么就攤上這事〕加伲” “怎么了橄霉?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長邑蒋。 經(jīng)常有香客問我姓蜂,道長,這世上最難降的妖魔是什么医吊? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任钱慢,我火速辦了婚禮中剩,結(jié)果婚禮上抠蚣,老公的妹妹穿的比我還像新娘。我一直安慰自己巷懈,他們只是感情好草描,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布览绿。 她就那樣靜靜地躺著,像睡著了一般穗慕。 火紅的嫁衣襯著肌膚如雪饿敲。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天逛绵,我揣著相機(jī)與錄音怀各,去河邊找鬼倔韭。 笑死,一個胖子當(dāng)著我的面吹牛瓢对,可吹牛的內(nèi)容都是我干的寿酌。 我是一名探鬼主播,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼沥曹,長吁一口氣:“原來是場噩夢啊……” “哼份名!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起妓美,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤僵腺,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后壶栋,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體辰如,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年贵试,在試婚紗的時候發(fā)現(xiàn)自己被綠了琉兜。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡毙玻,死狀恐怖豌蟋,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情桑滩,我是刑警寧澤梧疲,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站运准,受9級特大地震影響幌氮,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜胁澳,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一该互、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧韭畸,春花似錦宇智、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至隘马,卻和暖如春太防,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工蜒车, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留讳嘱,地道東北人。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓酿愧,卻偏偏與公主長得像沥潭,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子嬉挡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評論 2 348

推薦閱讀更多精彩內(nèi)容