Spring?Cloud?Eureka服務(wù)注冊中心入門流程分析
在學(xué)習(xí)Ribbon使用的時候,我們是直接在配置文件中寫死服務(wù)地址的,是不是特別的不方便?我們是不是需要一個統(tǒng)一的地方來維護(hù)這些服務(wù),以及這些配置發(fā)生變化后,我們不需要重啟服務(wù)。
所以這個時候需要引出一個新組件——eureka。
它主要可以幫助我們實現(xiàn)如下功能:
- 地址的統(tǒng)一維護(hù)服務(wù)提供者的動態(tài)上下線通知
- 服務(wù)提供者可以將服務(wù)注冊到eureka上,eureka通過鍵值對的形式將信息進(jìn)行保存。
服務(wù)消費(fèi)者可以直接根據(jù)KEY去eureka上獲取服務(wù)即可。
這里我們首先來看下eureka的整體架構(gòu)圖,逐步分析下具有那些流程:
Eureka 實現(xiàn)服務(wù)注冊與發(fā)現(xiàn)的流程如下:
- 搭建一個 Eureka Server 作為服務(wù)注冊中心;
- 服務(wù)提供者 Eureka Client 啟動時,會把當(dāng)前服務(wù)器的信息以服務(wù)名(spring.application.name)的方式注冊到服務(wù)注冊中心;
- 服務(wù)消費(fèi)者 Eureka Client 啟動時,也會向服務(wù)注冊中心注冊;
- 服務(wù)消費(fèi)者還會獲取一份可用服務(wù)列表,該列表中包含了所有注冊到服務(wù)注冊中心的服務(wù)信息(包括服務(wù)提供者和自身的信息);這個列表會緩存到消費(fèi)者本地,然后會定時輪詢更新。
- 在獲得了可用服務(wù)列表后,服務(wù)消費(fèi)者通過 HTTP 或消息中間件遠(yuǎn)程調(diào)用服務(wù)提供者提供的服務(wù)。
- 然后在Eureka中還有一個心跳檢測機(jī)制,從而實現(xiàn)我們的動態(tài)上下線感知。
項目搭建
了解了它的整體流程之后,我們來搭建一個Eureka服務(wù)。
搭建其實很簡單,我們直接創(chuàng)建一個Spring Boot 項目即可,然后選擇Eureka Server依賴即可。
最后只需在啟動程序上添加@EnableEurekaServer
注解即可。
這個時候啟動項目即可進(jìn)入Eureka的控制面板。(默認(rèn)端口8761,創(chuàng)建完項目后自行修改)
啟動項目之后,大家可能會遇到如下錯誤:Cannot execute request on any known server
簡單翻譯就是不能請求到任何確定的服務(wù)上。因為我們的eureka-server本身既是服務(wù)提供者又是一個項目,所以我們也需要將他自己注冊上去,那如何自己注冊自己呢?
我們只需要通過如下命令制定好注冊中心的地址即可,然后重新啟動項目,即可發(fā)現(xiàn)我們的服務(wù)已經(jīng)注冊上去了。這個地方的話可以不注冊,因為會默認(rèn)注冊到8761端口,但是如果搭建集群的話就需要我們自己指定了。
server.port=8761 # 指向服務(wù)注冊中心的地址 eureka.client.service-url.defaultZone=http://localhost:8761/eureka
我們也可以默認(rèn)不注冊,添加如下配置信息:
# 是否要注冊 eureka.client.register-with-eureka=false # 是否要更新注冊信息 eureka.client.fetch-registry=false
客戶端注冊
注冊中心搭建完成之后,我們需要將項目進(jìn)行注冊,首先需要引入相關(guān)依賴:
<!-- eureka 客戶端注冊--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
然后需要進(jìn)行注冊地址的配置:
# 注冊中心地址 eureka.client.service-url.defaultZone=http://localhost:8761/eureka
這個時候我們重新啟動這些項目,即可發(fā)現(xiàn)他們已經(jīng)注冊到eureka上了。
但是我們點擊后面的狀態(tài)時,是看不到任何數(shù)據(jù)的,這個時候我們需要引入actuator
。
<!--actuator--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
然后需要暴露相關(guān)端口,我這邊是直接暴露了所有,生產(chǎn)環(huán)境可不能這么操作。
management.endpoints.web.exposure.exclude=*
聚合層處理
既然我們已經(jīng)將各個模塊的項目注冊到eureka上了,我們在聚合層中就不需要在使用寫死的配置信息了。
我們將之前的配置信息注釋,然后將聚合層注冊到eureka上。這個時候可以發(fā)現(xiàn)我們的接口是可以正常下單的,說明我們的配置中心生效了,首先就完成了對地址信息統(tǒng)一維護(hù)的功能。
這就是我們?yōu)槭裁匆雜pring cloud的原因,極大的減少了我們的工作量。
Eureka架構(gòu)
上圖是Eureka的整體架構(gòu)的設(shè)計。
我們知道在微服務(wù)中,任何節(jié)點都是需要做高可用的,也就是不能是單節(jié)點。我們的Eureka也是,但是它的集群和我們之前接觸的集群是不同的,它沒有主從的概念,它所有的節(jié)點都是水平的,兩兩節(jié)點間的數(shù)據(jù)是可以相互復(fù)制的,任何一個客戶端都可以訪問任何一個節(jié)點。
因為Eureka遵守的是一個AP理論,這里主要需要保持一個高可用性,因為如果是主從模型,我們在主從同步的時候,如果發(fā)生延遲就會存在短期不可用,所以為了保持高可用性,就采用了這種無中心化的集群節(jié)點。
上圖中的一些關(guān)鍵名詞說明如下:
- Application Service: 作為Eureka Client,扮演了服務(wù)的提供者,提供業(yè)務(wù)服務(wù), 向Eureka Server注冊和更新自己的信息,同時能從Eureka Server的注冊表中獲取到 其他服務(wù)的信息。
- Eureka Server: 扮演服務(wù)注冊中心的角色,提供服務(wù)注冊和發(fā)現(xiàn)的功能,每個Eureka Cient向Eureka Server注冊自己的信息,也可以通過Eureka Server獲取到其他服務(wù)的 信息達(dá)到發(fā)現(xiàn)和調(diào)用其他服務(wù)的目的。
- Application Client: 作為Eureka Client,扮演了服務(wù)消費(fèi)者,通過Eureka Server獲取到注冊到上面的其他服務(wù)的信息,從而根據(jù)信息找到所需的服務(wù)發(fā)起遠(yuǎn)程調(diào) 用。
- Replicate: Eureka Server中的注冊表信息的同步拷貝,保持不同的Eureka Server 集群中的注冊表中的服務(wù)實例信息的一致性。提供了數(shù)據(jù)的最終一致性。
- Make Remote Call: 服務(wù)之間的遠(yuǎn)程調(diào)用。
- Register: 注冊服務(wù)實例,Client端向Server端注冊自身的元數(shù)據(jù)以進(jìn)行服務(wù)發(fā)現(xiàn)。
- Renew: 續(xù)約,通過發(fā)送心跳到Server維持和更新注冊表中的服務(wù)實例元數(shù)據(jù)的有效 性。當(dāng)在一定時長內(nèi)Server沒有收到Client的心跳信息,將默認(rèn)服務(wù)下線,將服務(wù)實例 的信息從注冊表中刪除。
- Cancel: 服務(wù)下線,Client在關(guān)閉時主動向Server注銷服務(wù)實例元數(shù)據(jù),這時Client 的的服務(wù)實例數(shù)據(jù)將從Server的注冊表中刪除。
集群搭建
Eureka的集群搭建是很簡單的,我們重新創(chuàng)建一個eureka-server模塊。和上文一樣的步驟即可,然后在配置文件中互相指定注冊地址。
eureka-server
# 應(yīng)用名稱 spring.application.name=eureka-server server.port=8761 # 指向服務(wù)注冊中心的地址 eureka.client.service-url.defaultZone=http://localhost:8762/eureka # 是否要注冊 #eureka.client.register-with-eureka=false # 是否要更新注冊信息 #eureka.client.fetch-registry=false
eureka-server-replica
# 應(yīng)用名稱 spring.application.name=eureka-server-replica server.port=8762 # 指向服務(wù)注冊中心的地址 eureka.client.service-url.defaultZone=http://localhost:8761/eureka
然后啟動項目,可以發(fā)現(xiàn)兩個項目已經(jīng)互相注冊了 。
由于我們之前的服務(wù)都是注冊到8761節(jié)點上的,這個時候我們隨便啟動一個服務(wù),可以發(fā)現(xiàn)8762節(jié)點上也會有相應(yīng)的服務(wù)。
我們需要讓其他服務(wù)也注冊到新的節(jié)點上嗎?其實是需要的,因為我們是去中心化的節(jié)點,所以如果8761節(jié)點掛了,那我們還能繼續(xù)注冊到8762節(jié)點上,保持我們的高可用性。多個節(jié)點我們只需要使用逗號隔開就可以。
eureka.client.service-url.defaultZone=http://localhost:8761/eureka,http://localhost:8762/eureka
多區(qū)域配置
我們搭建集群的時候為了實現(xiàn)災(zāi)備的功能,可以將各節(jié)點部署在不同的區(qū)域,然后客戶端獲取服務(wù)的時候可以從就近的區(qū)域獲取,如果就近區(qū)域節(jié)點宕機(jī)后照樣可以去獲取其他正常的節(jié)點服務(wù)。
實現(xiàn)這個功能也很簡單,接下來我們對各個項目進(jìn)行相關(guān)的配置。
我們這里主要對兩個eureka-server服務(wù)以及portal,goods-service項目進(jìn)行配置,首先因為是分區(qū),我們需要加上如下配置信息,表示地點在北京,以及北京地區(qū)的兩個區(qū)域機(jī)房。幾個項目都需要進(jìn)行如下的配置。
# 區(qū)域 eureka.client.region=beijing # 配置不同的機(jī)房 eureka.client.availability-zones.beijing=zone-1,zone-2 eureka.client.service-url.zone-1=http://localhost:8761/eureka eureka.client.service-url.zone-2=http://localhost:8762/eureka
然后我們來處理goods-service項目,因為我們之前以及做了一個簡易的集群,所以我們這里將配置文件復(fù)制出來,每個節(jié)點使用不同的配置文件。
每個配置文件中最后都需要指定該節(jié)點是屬于那個區(qū)域的。
# 應(yīng)用服務(wù) WEB 訪問端口 server.port=9090 # 注冊中心地址 #eureka.client.service-url.defaultZone=http://localhost:8761/eureka,http://localhost:8762/eureka eureka.client.region=beijing eureka.client.availability-zones.beijing=zone-1,zone-2 eureka.client.service-url.zone-1=http://localhost:8761/eureka eureka.client.service-url.zone-2=http://localhost:8762/eureka # 所屬區(qū)域 eureka.instance.metadata-map.zone=zone-1
我們的另一個節(jié)點需要指定配置文件。
goods-service處理完成后,我們在protal項目中進(jìn)行相同的配置,但是需要額外添加配置讓服務(wù)默認(rèn)調(diào)用同區(qū)域的服務(wù)。
eureka.client.region=beijing eureka.client.availability-zones.beijing=zone-1,zone-2 eureka.client.service-url.zone-1=http://localhost:8761/eureka eureka.client.service-url.zone-2=http://localhost:8762/eureka eureka.instance.metadata-map.zone=zone-1 # 默認(rèn)調(diào)用同區(qū)域的服務(wù) eureka.client.prefer-same-zone-eureka=true
這個時候我們將所有服務(wù)啟動,查看相應(yīng)效果。
可以看到所有的請求默認(rèn)都是到9090節(jié)點上的,這個時候我們將9090節(jié)點停止。
停止后,我們再次訪問可能會請求失敗,可以稍等會請求,這是由于停止后,9090節(jié)點的服務(wù)并沒有立刻從eureka下線,屬于自我保護(hù)機(jī)制的問題。
以上便是使用eureka進(jìn)行多區(qū)域配置的一個簡單演示。
Eureka自我保護(hù)機(jī)制
官方對于自我保護(hù)機(jī)制的定義:
自我保護(hù)模式正是一種針對網(wǎng)絡(luò)異常波動的安全保護(hù)措施,使用自我保護(hù)模式能使Eureka集群更加的健壯、穩(wěn)定的運(yùn)行。
自我保護(hù)機(jī)制的工作機(jī)制是:如果在15分鐘內(nèi)超過85%的客戶端節(jié)點都沒有正常的心跳,那么Eureka就認(rèn)為客戶端與注冊中心出現(xiàn)了網(wǎng)絡(luò)故障,Eureka Server自動進(jìn)入自我保護(hù)機(jī)制,此時會出現(xiàn)以下幾種情況:
- Eureka Server不再從注冊列表中移除因為長時間沒收到心跳而應(yīng)該過期的服務(wù)。
- Eureka Server仍然能夠接受新服務(wù)的注冊和查詢請求,但是不會被同步到其它節(jié)點上,保證當(dāng)前節(jié)點依然可用。
- 當(dāng)網(wǎng)絡(luò)穩(wěn)定時,當(dāng)前Eureka Server新的注冊信息會被同步到其它節(jié)點中。
因此Eureka Server可以很好的應(yīng)對因網(wǎng)絡(luò)故障導(dǎo)致部分節(jié)點失聯(lián)的情況,而不會像ZK那樣如果有一半不可用的情況會導(dǎo)致整個集群不可用而變成癱瘓。
我們可以通過如下參數(shù)配置比例:
eureka.server.renewal-percent-threshold=0.85
我們怎么確定是誰的85%沒有心跳則會觸發(fā)呢,是圖中所示的預(yù)期renew值,如果低于10*0.85的客戶端沒有續(xù)約,則進(jìn)入自我保護(hù)機(jī)制。
Renews threshold = 服務(wù)總數(shù) * 每分鐘的續(xù)約數(shù)量 (60s/客戶端續(xù)約(心跳)間隔時間) * renewal-percent-threshold
自我保護(hù)開關(guān)
Eureka自我保護(hù)機(jī)制,通過配置 eureka.server.enable-self-preservation
來true
打開/false
禁用自我保護(hù)機(jī)制,默認(rèn)打開狀態(tài),建議生產(chǎn)環(huán)境打開此配置。
心跳機(jī)制
上文的續(xù)約說到底就是我們的心跳機(jī)制,整體流程可以參考下圖。
Eureka實例信息存儲
上文說過我們是通過鍵值對來存儲服務(wù)信息的,整體結(jié)構(gòu)大致如下圖所示:
項目地址
到此這篇關(guān)于Spring Cloud Eureka服務(wù)注冊中心入門的文章就介紹到這了,更多相關(guān)Spring Cloud Eureka服務(wù)注冊內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java實現(xiàn)用Freemarker完美導(dǎo)出word文檔(帶圖片)
這篇文章主要介紹了Java實現(xiàn)用Freemarker完美導(dǎo)出word文檔(帶圖片),具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-07-07SpringBoot中使用Redis?Stream實現(xiàn)消息監(jiān)聽示例
本文主要介紹了SpringBoot中使用Redis?Stream實現(xiàn)消息監(jiān)聽示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06Spring Boot使用Servlet及Filter過程詳解
這篇文章主要介紹了Spring Boot使用Servlet及Filter過程詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-07-07