在跟我學(xué)Spring Cloud(Finchley版)-05-服務(wù)注冊(cè)與服務(wù)發(fā)現(xiàn)-Eureka入門(mén) 一節(jié)中,已經(jīng)編寫(xiě)了一個(gè)Eureka Server叮贩,并將服務(wù)提供者與消費(fèi)者都注冊(cè)到了Eureka Server上量瓜。
本節(jié)贷祈,來(lái)深入探討Eureka的高級(jí)特性滓侍。
Eureka原理
本節(jié)來(lái)探討Eureka的原理。
Region & Availability Zone
下面分析一下Eureka原理廉油,在分析原理前惠险,先來(lái)了解一下Region和Availability Zone,如下圖抒线。
眾所周知班巩,Netflix公司將他們的應(yīng)用都部署在了AWS上,所以Eureka的架構(gòu)使用到了AWS中的一些概念——不用擔(dān)心嘶炭,這不是說(shuō)Eureka和AWS環(huán)境綁定抱慌,Eureka可以部署在任意環(huán)境。
Region和Availability Zone均是AWS的概念眨猎。
- Region表示AWS中的地理位置抑进,例如us-east-1、us-east-2睡陪、eu-west-1等寺渗;
- 每個(gè)Region都有多個(gè)Availability Zone夕凝,彼此內(nèi)網(wǎng)打通;
- 各個(gè)Region之間完全隔離户秤,彼此內(nèi)網(wǎng)不打通;
- AWS通過(guò)這種方式實(shí)現(xiàn)了最大的容錯(cuò)和穩(wěn)定性逮矛。
Spring Cloud中鸡号,默認(rèn)使用的Region是us-east-1
。非AWS環(huán)境下须鼎,可將將Region理解為內(nèi)網(wǎng)沒(méi)有打通的機(jī)房鲸伴,將Availability Zone理解成相同機(jī)房的不同機(jī)架(內(nèi)網(wǎng)打通)。
拓展閱讀
- 如果您不了解AWS晋控,那你應(yīng)該聽(tīng)說(shuō)過(guò)阿里云汞窗,可以把AWS簡(jiǎn)單認(rèn)為是美國(guó)版的阿里云……
- 對(duì)Region和Availability Zone感興趣的讀者可前往http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html擴(kuò)展閱讀;
- 2017年AWS的S3發(fā)生故障赡译,受影響的大型網(wǎng)站列表中仲吏,Netflix赫然在列,有興趣可前往http://www.reibang.com/p/d5d1fd3151ad 拓展閱讀蝌焚。
Eureka架構(gòu)詳解
如圖是Eureka集群的工作原理裹唆。圖中的組件非常多,概念也比較抽象只洒,我們先來(lái)用通俗易懂的文字翻譯一下:
Application Service:服務(wù)提供者许帐;
Application Client:服務(wù)消費(fèi)者;
Make Remote Call調(diào)用RESTful API毕谴;
us-east-1c成畦、us-east-1d等都是Availability Zone,它們都屬于us-east-1這個(gè)region涝开。
由圖可知循帐,Eureka包含兩個(gè)組件:Eureka Server 和 Eureka Client,它們的作用如下:
Eureka Server提供服務(wù)發(fā)現(xiàn)的能力忠寻,各個(gè)微服務(wù)啟動(dòng)時(shí)惧浴,會(huì)向Eureka Server注冊(cè)自己的信息(例如IP、端口奕剃、微服務(wù)名稱(chēng)等)衷旅,Eureka Server會(huì)存儲(chǔ)這些信息;
Eureka Client是一個(gè)Java客戶(hù)端纵朋,用于簡(jiǎn)化與Eureka Server的交互柿顶;
微服務(wù)啟動(dòng)后,會(huì)周期性(默認(rèn)30秒)地向Eureka Server發(fā)送心跳以續(xù)約自己的“租期”操软;
如果Eureka Server在一定時(shí)間內(nèi)沒(méi)有接收到某個(gè)微服務(wù)實(shí)例的心跳嘁锯,Eureka Server將會(huì)注銷(xiāo)該實(shí)例(默認(rèn)90秒);
默認(rèn)情況下,Eureka Server同時(shí)也是Eureka Client家乘。多個(gè)Eureka Server實(shí)例蝗羊,互相之間通過(guò)增量復(fù)制的方式,來(lái)實(shí)現(xiàn)服務(wù)注冊(cè)表中數(shù)據(jù)的同步仁锯。Eureka Server默認(rèn)保證在90秒內(nèi)耀找,Eureka Server集群內(nèi)的所有實(shí)例中的數(shù)據(jù)達(dá)到一致(從這個(gè)架構(gòu)來(lái)看,Eureka Server所有實(shí)例所處的角色都是對(duì)等的业崖,沒(méi)有類(lèi)似Zookeeper野芒、Consul、Etcd等軟件的選舉過(guò)程双炕,也不存在主從狞悲,所有的節(jié)點(diǎn)都是主節(jié)點(diǎn)。Eureka官方將Eureka Server集群中的所有實(shí)例稱(chēng)為“對(duì)等體(peer)”)
Eureka Client會(huì)緩存服務(wù)注冊(cè)表中的信息妇斤。這種方式有一定的優(yōu)勢(shì)——首先摇锋,微服務(wù)無(wú)需每次請(qǐng)求都查詢(xún)Eureka Server,從而降低了Eureka Server的壓力站超;其次乱投,即使Eureka Server所有節(jié)點(diǎn)都宕掉,服務(wù)消費(fèi)者依然可以使用緩存中的信息找到服務(wù)提供者并完成調(diào)用顷编。
綜上戚炫,Eureka通過(guò)心跳檢查、客戶(hù)端緩存等機(jī)制媳纬,提高了系統(tǒng)的靈活性双肤、可伸縮性和可用性。
TIPS
事實(shí)上钮惠,這個(gè)官方架構(gòu)圖是有一點(diǎn)問(wèn)題的:Eureka Server本身也集成了Eureka Client茅糜,彼此通過(guò)Eureka Client同步數(shù)據(jù)給其它實(shí)例又或者從其他實(shí)例同步數(shù)據(jù)——現(xiàn)在,你應(yīng)該能理解上一節(jié)中所使用的 register-with-eureka
以及fetch-registry
的作用了素挽。
高可用
編寫(xiě)高可用Eureka Server
下面來(lái)編寫(xiě)一個(gè)雙節(jié)點(diǎn)Eureka Server集群蔑赘。編寫(xiě)這個(gè)集群非常簡(jiǎn)單,只需修改單實(shí)例Eureka Server的配置即可:
- 為系統(tǒng)配置主機(jī)名:
vim /etc/hosts
# 添加如下內(nèi)容
127.0.0.1 peer1 peer2
對(duì)于Windows系統(tǒng)预明,請(qǐng)修改C:\windows\system32\drivers\etc\hosts文件
- 配置:
spring:
application:
name: microservice-discovery-eureka-ha
---
spring:
profiles: peer1 # 指定profile=peer1
server:
port: 8761
eureka:
instance:
hostname: peer1 # 指定當(dāng)profile=peer1時(shí)缩赛,主機(jī)名是peer1
client:
serviceUrl:
defaultZone: http://peer2:8762/eureka/ # 將自己注冊(cè)到peer2這個(gè)Eureka上面去
---
spring:
profiles: peer2
server:
port: 8762
eureka:
instance:
hostname: peer2
client:
serviceUrl:
defaultZone: http://peer1:8761/eureka/
由配置不難看出我們?cè)O(shè)置了兩個(gè)Profile:peer1、peer2撰糠。兩個(gè)Profile下各有一個(gè)Eureka Server酥馍,通過(guò)相互注冊(cè)的方式,構(gòu)建了Eureka Server集群阅酪。
- 啟動(dòng):
java -jar microservice-discovery-eureka-ha-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer1
java -jar microservice-discovery-eureka-ha-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer2
第一個(gè)實(shí)例會(huì)報(bào)錯(cuò)旨袒,這是正常的汁针,因?yàn)樗鼤?huì)嘗試連接第二個(gè)實(shí)例,但第二個(gè)實(shí)例尚未啟動(dòng)砚尽,所以會(huì)報(bào)連接不上的異常施无。
注意點(diǎn)
-
如果兩個(gè)Eureka Server實(shí)例在同一臺(tái)機(jī)器上啟動(dòng),那么配置hosts的這一步不能少必孤。原因:Eureka Server對(duì)端口是不敏感的帆精,這意味著,如果直接用IP的形式(例如地址寫(xiě)成
http://127.0.0.1:8761/eureka/
)相互注冊(cè)隧魄,Eureka Server誤認(rèn)為兩個(gè)Eureka Server實(shí)例是一個(gè)實(shí)例——這會(huì)造成Eureka Server首頁(yè)顯示不正常等一系列問(wèn)題!隘蝎!
拓展閱讀
- 考慮到有童鞋對(duì)Spring Boot的Profile不熟悉购啄,貼個(gè)拓展閱讀吧:https://blog.csdn.net/j080624/article/details/80507927
TIPS
編寫(xiě)Eureka Server集群的簡(jiǎn)寫(xiě)方式:
spring:
application:
name: microservice-discovery-eureka-ha
eureka:
client:
serviceUrl:
defaultZone: http://peer2:8762/eureka/,http://peer1:8761/eureka/
---
spring:
profiles: peer1
server:
port: 8761
eureka:
instance:
hostname: peer1
---
spring:
profiles: peer2
server:
port: 8762
eureka:
instance:
hostname: peer2
將應(yīng)用注冊(cè)到Eureka Server集群上
以microservice-provider-user
項(xiàng)目為例,只須修改eureka.client.serviceUrl.defaultZone
嘱么,配置多個(gè)Eureka Server地址狮含,就可以將其注冊(cè)到Eureka Server集群了。示例:
eureka:
client:
serviceUrl:
defaultZone: http://peer1:8761/eureka/,http://peer2:8762/eureka/
這樣就可以將服務(wù)注冊(cè)到Eureka Server集群上了曼振。
當(dāng)然几迄,微服務(wù)即使只配置Eureka Server集群中的某個(gè)節(jié)點(diǎn),也能正常注冊(cè)到Eureka Server集群冰评,因?yàn)槎鄠€(gè)Eureka Server之間的數(shù)據(jù)會(huì)相互同步映胁。例如:
eureka:
client:
serviceUrl:
defaultZone: http://peer1:8761/eureka/
正常情況下,這種方式與配置多個(gè)Server節(jié)點(diǎn)的效果是一樣的甲雅。不過(guò)為適應(yīng)某些極端場(chǎng)景解孙,筆者建議在客戶(hù)端配置多個(gè)Eureka Server節(jié)點(diǎn)。
應(yīng)用啟動(dòng)后抛人,訪問(wèn)Eureka Server應(yīng)能看到類(lèi)似如下的界面:
RESTful API
前文說(shuō)過(guò)弛姜,Eureka本身是一個(gè)基于REST的服務(wù)。本節(jié)來(lái)探討Eureka Server的RESTful API妖枚。
下表展示了Eureka Server提供的RESTful API廷臼,來(lái)自https://github.com/Netflix/eureka/wiki/Eureka-REST-operations ,只需按表格向Eureka Server發(fā)送請(qǐng)求绝页,即可操作Eureka Server中的數(shù)據(jù)荠商。
Operation | HTTP action | Description |
---|---|---|
Register new application instance | POST /eureka/apps/appID | Input:JSON/XMLpayload HTTPCode: 204 on success |
De-register application instance | DELETE /eureka/apps/appID/instanceID | HTTP Code: 200 on success |
Send application instance heartbeat | PUT /eureka/apps/appID/instanceID | HTTP Code:* 200 on success* 404 if instanceID doesn’t exist |
Query for all instances | GET /eureka/apps | HTTP Code: 200 on success Output:JSON/XML |
Query for all appIDinstances | GET /eureka/apps/appID | HTTP Code: 200 on success Output:JSON/XML |
Query for a specificappID/instanceID | GET /eureka/apps/appID/instanceID | HTTP Code: 200 on success Output:JSON/XML |
Query for a specificinstanceID | GET /eureka/instances/instanceID | HTTP Code: 200 on success Output:JSON/XML |
Take instance out of service | PUT /eureka/apps/appID/instanceID/status?value=OUT_OF_SERVICE | HTTP Code:* 200 on success* 500 on failure |
Put instance back into service (remove override) | DELETE /eureka/apps/appID/instanceID/status?value=UP (The value=UP is optional, it is used as a suggestion for the fallback status due to removal of the override) | HTTP Code:* 200 on success* 500 on failure |
Update metadata | PUT /eureka/apps/appID/instanceID/metadata?key=value | HTTP Code:* 200 on success* 500 on failure |
Query for all instances under a particular vip address | GET /eureka/vips/vipAddress | HTTP Code: 200 on success Output:JSON/XML 404 if thevipAddress**does not exist. |
Query for all instances under a particular secure vip address | GET /eureka/svips/svipAddress | HTTP Code: 200 on success Output:JSON/XML 404 if thesvipAddress**does not exist. |
調(diào)用示例
示例1:注冊(cè)一個(gè)服務(wù):
- 將以下文件存儲(chǔ)為rest-api-test.xml
<instance>
<instanceId>itmuch:rest-api-test:9000</instanceId>
<hostName>itmuch</hostName>
<app>REST-API-TEST</app>
<ipAddr>127.0.0.1</ipAddr>
<vipAddress>rest-api-test</vipAddress>
<secureVipAddress>rest-api-test</secureVipAddress>
<status>UP</status>
<port enabled="true">9000</port>
<securePort enabled="false">443</securePort>
<homePageUrl>http://127.0.0.1:9000/</homePageUrl>
<statusPageUrl>http://127.0.0.1:9000/info</statusPageUrl>
<healthCheckUrl>http://127.0.0.1:9000/health</healthCheckUrl>
<dataCenterInfo class="com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo">
<name>MyOwn</name>
</dataCenterInfo>
</instance>
- 通過(guò)cURL調(diào)用Eureka Server
cat ./rest-api-test.xml | curl -v -X POST -H "Content-type: application/xml" -d @- http://localhost:8761/eureka/apps/rest-api-test
示例2:查看指定服務(wù)的所注冊(cè)的信息
只需訪問(wèn):http://Eureka Server的地址/eureka/apps/microservice-provider-user
即可查看microdervice-provider-user
服務(wù)的信息。
RESTful API的意義
你可能會(huì)問(wèn):我們不是已經(jīng)有Eureka Client了嗎续誉?誰(shuí)閑著沒(méi)事再去用RESTful API敖崽洹?
要知道屈芜,微服務(wù)的優(yōu)勢(shì)之一就是允許使用異構(gòu)的技術(shù)郊愧、異構(gòu)的語(yǔ)言甚至異構(gòu)的平臺(tái)解決你想解決的問(wèn)題朴译。
舉個(gè)例子,如果你有一個(gè)系統(tǒng)属铁,一部分是Spring Cloud構(gòu)建的眠寿,一部分是用世界上最好的語(yǔ)言PHP寫(xiě)的!但是呢焦蘑,你希望Java應(yīng)用與PHP應(yīng)用之間的通信也能享受服務(wù)發(fā)現(xiàn)所帶來(lái)的好處盯拱,此時(shí)就可編寫(xiě)一個(gè)基于PHP的Eureka Client,將PHP應(yīng)用也注冊(cè)到Eureka Server例嘱!
事實(shí)上狡逢,前文說(shuō)的Eureka Client不過(guò)是一個(gè)用Jersey 1.x封裝了RESTful API的Jar包而已。
拓展閱讀
事實(shí)上拼卵,業(yè)界已經(jīng)有一些不同語(yǔ)言的Eureka Client奢浑,例如:
- Node.js版的Eureka Client:https://www.npmjs.com/package/eureka-js-client
- Python版的Eureka Client:https://github.com/keijack/python-eureka-client
自我保護(hù)模式
自我保護(hù)模式是Eureka的重要特性,筆者之前已經(jīng)專(zhuān)題寫(xiě)過(guò)文章詳解了腋腮,所以本系列不再贅述雀彼,詳見(jiàn):理解Eureka的自我保護(hù)模式
用戶(hù)認(rèn)證
Finchley版本相對(duì)之前的版本有些改動(dòng),比較重要即寡。詳見(jiàn): 跟我學(xué)Spring Cloud(Finchley版)番外-01-Eureka安全詳解 徊哑。
配套代碼
- GitHub:
- microservice-discovery-eureka-ha:https://github.com/eacdy/spring-cloud-study/tree/master/2018-Finchley/microservice-discovery-eureka-ha
- Gitee:
- microservice-discovery-eureka-ha:https://gitee.com/itmuch/spring-cloud-study/tree/master/2018-Finchley/microservice-discovery-eureka-ha
相關(guān)文章
- 跟我學(xué)Spring Cloud(Finchley版)-05-服務(wù)注冊(cè)與服務(wù)發(fā)現(xiàn)-Eureka入門(mén)
- 跟我學(xué)Spring Cloud(Finchley版)番外-01-Eureka安全詳解
- 跟我學(xué)Spring Cloud(Finchley版)-04-服務(wù)注冊(cè)與服務(wù)發(fā)現(xiàn)-原理剖析
- 關(guān)于Eureka 2.x,別再人云亦云了聪富!
- Spring Cloud Alibaba遷移指南1:零代碼從Eureka遷移到Nacos
本文鏈接:跟我學(xué)Spring Cloud(Finchley版)-06-服務(wù)注冊(cè)與服務(wù)發(fā)現(xiàn)-Eureka深入
轉(zhuǎn)載聲明:本博客由周立創(chuàng)作莺丑,采用 CC BY 3.0 CN 許可協(xié)議《章可自由轉(zhuǎn)載窒盐、引用,但需署名作者且注明文章出處钢拧。