您好,登錄后才能下訂單哦!
這篇文章主要講解了“什么是Eureka”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“什么是Eureka”吧!
什么是服務注冊?
首先我們來了解下,服務注冊、服務發現和服務注冊中心的之間的關系。
舉個形象的例子,三者之間的關系就好像是供貨商,顧客和商店。
首先各地的供貨商會將各種商品提供給商店,然后顧客需要商品的時候會去商店購買。
注冊中心就好比是這個商店,供貨商的動作就是服務注冊,商品就是注冊的服務。
當部署的服務啟動后,會注冊到注冊中心,消費者需要什么樣的服務,就自己去注冊中心拉取。
那么到底什么是服務注冊,為什么要將服務注冊到注冊中心呢?
服務注冊指的是服務在啟動時將服務的信息注冊到注冊中心中,由注冊中心統一對所有的注冊的服務進行管理。
現在我們想想,假如你是消費者,你需要買一個商品,你可以去商店,也可以直接去供貨商。
但是如果今天你要買很多商品,而且我們并不知道每個商品對應的供應商的地址,那么你就得挨家挨戶的去跑供貨商購買商品。
是不是就很麻煩了,倘若此時有一家商店,匯總了多家供貨商的商品,那你是不是只需要去這一家商店就能購買到你需要的所有的商品了呢?
這樣是不是就方便了。
在我們現實開發中,比如我們需要獲取用戶信息的時候,而此時,我們的用戶服務只部署了一個節點,那我們就可以使用IP+端口的形式訪問服務。
當此時我們的服務部署了10個節點后,我們可以通過域名訪問,通過nginx轉發到某一個節點上,訪問該節點的服務。
使用過nginx的小伙伴們都知道,每當我們需要新增一個節點的時候,我們就需要去修改nginx的配置文件,一旦服務部署的節點過多,頻繁修改配置文件就變成了一件極其麻煩的事情。
這個時候,我們的注冊中心,就應該粉墨登場了。
注冊中心一登場,我們就盡管部署服務節點,部署完成后,服務啟動,服務的信息就會被注冊到注冊中心,我們就不需要擔心是不是又要去修改配置文件了。
什么是服務發現?
服務發現有兩種模式:一種是客戶端發現模式,一種是服務端發現模式。Eureka采用的是客戶端發現模式。
客戶端發現模式就好比我是一個土豪顧客,我去了商店,我把所有的商品都買回家,需要的時候在這些商品里面尋找。
因為我是土豪,所以我當然不能忍受商店里有新品上架,而我卻沒有,所以我每隔一段時間就會商店增量獲取最新的商品。
這就是Eureka中的Fetch Registry,抓取注冊信息。
Eureka Client 從 Eureka Server 獲取注冊表信息并在本地緩存。
這里我們注意一下,Eureka Client并不是直接去服務注冊表中獲取數據,而是從ReadOnly緩存中獲取數據。
并且會通過在上一個獲取周期和當前獲取周期之間獲取增量更新,這些信息會定期更新(每30秒更新一次)。
獲取的時候可能返回相同的實例。Eureka Client會自動處理重復信息。
因為我的土豪行為,我已經被商店老板記錄在它的VVIP名單上了。可惜天有不測風云,我破產了,我再也不能這么土豪了,沒辦法,我告訴了老板我破產了,老板聽了我的話,想都沒想,直接從他的VVIP名單上將我的名字給剔除了,社會就是這么現實。
這就是Eureka中的Cancel,取消。
每一個微服務節點關閉時,Eureka Client會向Eureka Server發送一個取消請求。
Eureka Server收到你的取消請求后,就會將你從服務注冊表中給剔除。
商店老板是個傲嬌的人,她制定了一個規則,如果你是她VVIP名單上的人,你必須每隔一段時間就要去商店采購商品。
一旦你在一段時間內沒有來采購,她就覺得你已經沒有購買能力,不適合在她的VVIP名單上存在了。
她就會狠心的將你從她的VVIP名單上將我的名字給剔除了。
這就是Eureka中的Renew(更新 / 續借)
Eureka Client 內部具備一個內置的負載均衡器,它使用輪訓(round-robin)負載算法。
在服務啟動后,每隔一定周期(默認30秒)向Eureka Server發送心跳。
如果Eureka Server在多個心跳周期內(默認90秒)沒有收到Eureka Client發送過來的心跳,Eureka Server將會在服務注冊表中將該節點剔除。
當然了,服務發現去注冊中心拉取的是服務的信息,然后需要從服務信息中獲取到服務部署的節點信息,然后通過域名地址訪問到該節點的服務。
就好像一家商店,因為空間太小,只是存放了一些商品的微縮模型,模型上寫著該商品所屬的供貨商地址,我們去商店拿到該模型后,看到供貨商的地址,然后我們就可以直接去供貨商那兒直接購買商品了。
什么是注冊中心,注冊中心的作用?
注冊中心就是一個管理器,各個服務提供者將服務注冊到注冊中心,有注冊中心進行統一的存儲和管理。
注冊中心同時還有著判斷服務是否可用,對于不可用的服務進行剔除的功能。
至于如何判斷服務的可用性和如何剔除不可用的服務,后續會有詳細的講解。
什么是 Eureka,有什么作用?
Eureka采用CS架構,它分為兩大組件。
一個是Eureka Server,注冊中心服務端。
當各個微服務節點啟動后,Eureka Server 會存儲服務提供者注冊上來的服務信息,并且提供二層緩存機制來維護整個注冊中心。
另一個是Eureka Client,注冊中心客戶端。
Eureka Client是一個java客戶端,它用來簡化和Eureka Server交互。
Eureka Client 會拉取、更新和緩存 Eureka Server 中的信息。
因此當所有的 Eureka Server 節點都宕掉,服務消費者依然可以使用緩存中的信息找到服務提供者,但是當服務有更改的時候會出現信息不一致。
Eureka 架構詳解
如下圖所示,這是官網提供給我們的Eureka的架構圖Eureka 的架構,主要分為 Eureka Server 和 Eureka Client 兩部分,Eureka Client 又分為 Applicaton Service 和 Application Client,Applicaton Service 就是服務提供者,Application Client 就是服務消費者。
我們首先會在應用程序中依賴 Eureka Client,項目啟動后 Eureka Client 會向 Eureka Server 發送請求,進行注冊,并將自己的一些信息發送給 Eureka Server。
注冊成功后,每隔一定的時間,Eureka Client 會向 Eureka Server 發送心跳來續約服務,也就是匯報健康狀態。如果客戶端長時間沒有續約,那么 Eureka Server 大約將在 90 秒內從服務器注冊表中刪除客戶端的信息。
Eureka Client 還會定期從 Eureka Server 拉取注冊表信息,然后根據負載均衡算法得到一個目標,并發起遠程調用,關于負載均衡在后面的課時會詳細介紹,也就是 Ribbon 組件。
應用停止時也會通知 Eureka Server 移除相關信息,信息成功移除后,對應的客戶端會更新服務的信息,這樣就不會調用已經下線的服務了,當然這個會有延遲,有可能會調用到已經失效的服務,所以在客戶端會開啟失敗重試功能來避免這個問題。
Eureka Server 會有多個節點組成一個集群,保證高可用。Eureka Server 沒有集成其他第三方存儲,而是存儲在內存中。
所以 Eureka Server 之間會將注冊信息復制到集群中的 Eureka Server 的所有節點。
這樣數據才是共享狀態,任何的 Eureka Client 都可以在任何一個 Eureka Server 節點查找注冊表信息。
Eureka 的工作流程
Eureka 的自我保護機制
什么是自我保護機制
官方定義:自我保護模式正是一種針對網絡異常波動時的安全保護措施,使用自我保護模式能使Eureka集群更加健壯穩定的運行。
為什么要開啟自我保護機制?
如果Eureka Server在一定時間內(默認90s)(可優化)沒有收到某一個服務節點的心跳,Eureka Server將會移除該服務實例。
但是在某些時候,遇到網絡分區故障,服務節點實際上是正常存貨狀態,但是卻無法和Eureka Server正常通信,此時如果沒有引入自我保護機制,Eureka Server就會將該服務節點剔除。
自我保護模式的工作機制
如果15分鐘內超過85%的客戶端節點都沒有正常的心跳,那么Eureka Server就會認為客戶端與注冊中心發生了網絡故障,Eureka Server進入自我保護機制。
自我保護機制的缺點
如果在自我保護機制中,剛好某些服務節點非正常下線,但是Eureka Server并不會剔除該服務節點,服務消費者就會獲取到一個無效的服務實例。
解決方案
① :關閉自我保護機制(不推薦)
② :切換請求或斷路器,使用負載均衡的方式,設置當一個請求超過多少秒還未得到響應,速度切換請求到下一個注冊服務,例如使用Ribbon+Hystrix配置負載均衡和斷路器。
Eureka Server 進入自我保護機制后
1、Eureka Server不在從注冊表中剔除因為長時間沒有和注冊中心續約的服務節點
2、Eureka Server仍然能夠接受新服務的注冊和查詢請求,但是不會同步到其他Eureka Server節點上
3、網絡正常后,當前Eureka Server節點會將新的服務節點信息同步到其他Eureka Server節點上
如何開啟自我保護
通過eureka.server.enable-self-preservation=true/false來開啟或關閉自我保護機制。
其他關鍵配置:
清理失效服務節點的時間間隔:eureka.server.evication-interval-timer-in-ms默認60s
續約間隔時間:eureka.instance.lease-renewal-interval-in-seconds默認30s
續約到期時間:eureka.instance.lease-expiration-duration-in-seconds默認90s
通過源碼窺探Eureka是如何開啟自我保護機制的
第一步,我們引入Eureka Server 依賴。
第二步,我們找到eureka-core jar包下的路徑為com.netflix.eureka下的registry包
第三步,進入AbstractInstanceRegistry 類,找到evict方法,這個是定期剔除任務的線程最終執行的方法
public void evict(long additionalLeaseMs) { logger.debug("Running the evict task"); //判斷自動保護是否開啟,如果開啟了自動保護, //那么剔除服務的操作就不往下執行,就不會剔除服務了 if (!this.isLeaseExpirationEnabled()) { logger.debug("DS: lease expiration is currently disabled."); } else { ... } }
第四步,我們找到isLeaseExpirationEnabled()方法的實現
public boolean isLeaseExpirationEnabled() { //首先判斷是否在配置文件中關閉了自我保護,如果關閉了自我保護直接返回true, // evict方法也就可以繼續往下執行,進行無用服務剔除操作 if (!this.isSelfPreservationModeEnabled()) { return true; } else { //如果開啟了自我保護機制,則進一步判斷是否開啟自我保護機制 //numberOfRenewsPerMinThreshold(每分鐘最小的續約次數)大于0 //而且getNumOfRenewsInLastMin(最后一分鐘的續約次數)必須要大于每分鐘最小的續約次數 //當滿足上面兩個條件時則說明續約正常,返回true,evict方法也就可以繼續往下執行,進行無用服務剔除操作 //所以說,只有不滿足上述兩個條件的情況下,才會返回false,evict方法也就不在往下執行,即使有沒有正常續約的服務,也不會剔除 return this.numberOfRenewsPerMinThreshold > 0 && this.getNumOfRenewsInLastMin() > (long)this.numberOfRenewsPerMinThreshold; } }
第五步,我們注意到numberOfRenewsPerMinThreshold這個變量很關鍵,它的含義是每分鐘最小的續約次數
在服務注冊register和服務下線cancel兩個方法中會更新這個變量,更新該變量方法如下:
/** * 期望每分鐘最小的續約次數 = 期望正常續約的服務實例數 * (60/(我們配置的發送一次心跳時間間隔(默認30秒)))*0.85 * serverConfig.getRenewalPercentThreshold() 默認是 0.85 (可以通過eureka.server.renewal-percent-threshold)進行配置 **/ protected void updateRenewsPerMinThreshold() { this.numberOfRenewsPerMinThreshold = (int)((double)this.expectedNumberOfClientsSendingRenews * (60.0D / (double)this.serverConfig.getExpectedClientRenewalIntervalSeconds()) * this.serverConfig.getRenewalPercentThreshold()); }
以上就是Eureka開啟自我保護的整個邏輯流程。
解除自我保護機制
1.當服務的網絡分區故障解除之后,客戶端能夠和服務進行交互時,在續約的時候,更新每分鐘的續約數,當每分鐘的續約數大于85%時,則自動解除。
2.重啟服務
Eureka 的健康檢查
其實很多框架的健康狀態監控都是通過actuator來管理健康狀態的,并且擴展了health端點。
所以說我們只要在項目中集成Actuator,我們就能管理監控項目的健康狀態。
Eureka也是一樣,我們可以將某些不健康的服務節點的狀態告知Eureka Server,然后Eureka Server 會主動讓其下線。
這個就是Eureka的健康檢查。
如何實現Eureka-Actuator健康檢查?
首先我們要在pom中依賴spring-boot-starter-actuator。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> <version>2.3.3.RELEASE</version> </dependency>
第二步,配置文件中添加 eureka.client.healthcheck.enabled=true 配置
原理分析:
首先在EurekaDiscoveryClientConfiguration 中根據 eureka.client.healthcheck.enabled 的值來決定是否要裝配 EurekaHealthCheckHandler,然后在 EurekaClientAutoConfiguration 中會注冊 HealthCheck,但我們注冊完成后會有調用任務來進行狀態的更新,在com.netflix.discovery.InstanceInfoReplicator.run() 中會進行狀態更新。
Eureka 的多級緩存機制
什么是多級緩存機制
Eureka Server 為了避免同事讀取內存數據造成的并發沖突問題,采用了多級緩存機制提升服務請求的響應速度。
Eureka Server的緩存是通過一個只讀,一個讀寫緩存來實現的。
一級緩存:concurrentHashMap<key,value>readOnlyCacheMap本質是HashMap,無過期時間,保存數據信息對外輸出。
readOnlyCacheMap依賴于定時器的更新,通過與readWriteCacheMap的值做對比,以readWriteCacheMap為準。
responseCacheUpdateIntervalMs:readOnlyCacheMap緩存更新間隔,默認30s
二級緩存:LoaDing<key,value>readWriteCacheMap本質是Guava緩存,包含失效機制,保護數據信息對外輸出。
responseCacheAutoExpirationInSeconds:readWriteCacheMap 緩存過期時間,默認180s。
當服務節點發生注冊,下線,過期,狀態變更等變化時
1.在內存中更新注冊表信息
2.同時過期掉readWriteCacheMap緩存,緩存清除只是會去清除readWriteCacheMap這個緩存, readOnlyCacheMap 只讀 緩存并沒有更新,也就說當客戶端的信息發生變化之后, 只讀緩存不是第一時間感知到的。只讀緩存的更新只能依賴那個30秒的定時任務來更新。
3.一段時間后(默認30s),后臺線程發現readWriteCacheMap緩存為空,于是也將readOnlyCacheMap中的緩存清空
4.當有服務消費者拉取注冊表信息時,會調用ClassLoader的load方法,將內存中的注冊表信息加載到各級緩存中,并返回注冊表信息。
在Eureka Server 中會有兩個線程,一個是定時同步兩個緩存的數據,默認30s,一個是定時檢測心跳故障,默認90s。
服務拉取
1.服務消費者,默認每30s,拉取注冊表信息
2.從readOnlyCacheMap中獲取信息,如果獲取為空
3.從readWriteCacheMap中獲取,如果還是為空
4.調用ClassLoader的load方法,將內存中的注冊表信息加載到各級緩存中,并返回注冊表信息。
Eureka的區域配置
當用戶地理分布范圍很廣的時候,比如公司在上海、杭州、青島等都有分公司的時候,一般都會有多個機房。
那么對于用戶而言,當然是希望調用本地分公司的機房中的微服務應用。
比如:上海用戶A,調用OAuth3服務,用戶A當然希望調用上海機房里面的微服務應用。如果上海用戶A調用杭州機房的OAuth3服務,就增加的延時時間。
所以我們希望一個機房內的服務優先調用同一個機房內的服務,當同一個機房的服務不可用的時候,再去調用其它機房的服務,以達到減少延時的作用。
為此,eureka提供了region和zone兩個概念來進行分區,Eureka基于Amazon設計的,所以對于地域的區分也與Amazon一致,Amazon分為多個region,每個region包含多個zone,所以Eureka設計時也是可以設置region與zone,請求時可以優先選擇與請求服務在同一個zone的服務。
基本配置
eureka: client: region: shanghai availability-zones: shanghai: zone1, zone2 service-url: zone1: http://localhost:8081/eureka, http://localhost:8082/eureka zone2: http://localhost:8083/eureka, http://localhost:8084/eureka instance: metadata-map: zone: zone1
此時無論我們調用多少次,調用的都是shanghai下面的zone1下面的服務。
一般來說我們都會結合Ribbon來實現微服務的負載均衡,而Ribbon內部會有一些專門的負載策略算法,雖然剛剛我們說過會優先請求的是指定region下指定 Zone 區域的服務實例。
但有些時候比如當在Region=shanghai下沒有可用的zone,系統會默認加載 DEFAULT_ZONE,或者說活著同區域的服務負載過高...等等,也會自動切換成其他區域的服務。
Eureka的重試機制
由于 Spring Cloud Eureka 實現的服務治理機制強調了 CAP 原理中的 AP,即可用性與可靠性,犧牲了一定的一致性(在極端情況下它寧愿接受故障實例也不要丟掉"健康"實例,如同如我們上面所說的自我保護機制)。
但不論是由于觸發了保護機制還是服務剔除的延遲,引起服務調用到這些不正常的服務,調用就會失敗,從而導致其它服務不能正常工作!
這顯然不是我們愿意看到的,我們還是希望能夠增強對這類問題的容錯。所以,我們在實現服務調用的時候通常會加入一些重試機制。
從 Camden SR2 版本開始,Spring Cloud 就整合了 Spring Retry 來增強 RestTemplate 的重試能力,對于開發者來說只需通過簡單的配置,原來那些通過 RestTemplate 實現的服務訪問就會自動根據配置來實現重試策略。
開啟Eureka的重試機制很簡單,首先我們在pom中引入Spring Retry的依賴:
<dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency>
然后在配置文件中配置spring.cloud.loadbalancer.retry.enabled參數來控制重試機制的開關,因為 Spring Retry默認是開啟的,所以說我們只要引入依賴即可,如果說我們想要關閉的話只需要將 spring.cloud.loadbalancer.retry.enabled設置為false即可。
其實在SpringCloud的架構組件中無論是Fegin,Ribbon,還是Zuul都提供了重試機制,這些暫且不論,后續再講到具體的組件時再進行具體的分析。
實戰 Eureka 注冊中心的部署
Eureka Server 項目搭建
1、創建一個 springcloud-eureka-server 的項目,然后在 pom 中增加 spring-cloud-starter-netflix-eureka-server 的依賴。
2.在pom.xml文件中新增spring-cloud-starter-netflix-eureka-server依賴
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency>
3.在啟動類SpringcloudEurekaServerApplication上使用 @EnableEurekaServer 開啟 EurekaServer 的自動裝配功能。
@SpringBootApplication @EnableEurekaServer public class SpringcloudEurekaServerApplication { public static void main(String[] args){ SpringApplication.run(SpringcloudEurekaServerApplication.class, args); } }
4.添加配置文件application.properties
# server (eureka 默認端口為:8761) server.port=8761 # spring spring.application.name=spring-cloud-eureka-server # eureka # 是否注冊到eureka eureka.client.register-with-eureka=false # 是否從eureka獲取注冊信息 eureka.client.fetch-registry=false # eureka服務器的地址(注意:地址最后面的 /eureka/ 這個是固定值) eureka.client.serviceUrl.defaultZone=http://localhost:${server.port}/eureka/
5.啟動項目,然后訪問http://localhost:8761/,可以看到 Eureka 的管理頁面,表示 Eureka 啟動成功了。
1、創建一個 springcloud-eureka-client 的項目,然后在 pom 中增加 spring-cloud-starter-netflix-eureka-client 的依賴。
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency>
2.在啟動類SpringcloudEurekaClientApplication上使用 @EnableEurekaClient 開啟 EurekaServer 的自動裝配功能。
@SpringBootApplication @EnableEurekaClient public class SpringcloudEurekaClientApplication { public static void main(String[] args) { SpringApplication.run(SpringcloudEurekaClientApplication.class, args); } }
配置 eureka.client.serviceUrl.defaultZone 的地址,也就是剛剛啟動的 Eureka Server 的地址,http://localhost:8761/eureka/。
server.port=8762 spring.application.name=spring-cloud-eureka-client eureka.client.serviceUrl.defaultZoon=http://localhost:8761/eureka/
啟動客戶端,然后刷新剛剛打開的Eureka主頁,我們發現服務已經注冊成功。
Eureka 注冊中心添加密碼認證
上面我們看到我們搭建好Eureka Server 后訪問http://localhost:8761/,沒有登陸就可以直接看到 Eureka 的管理頁面。
如果在實際使用中,注冊中心地址有公網 IP 的話,必然能直接訪問到,這樣是不安全的。所以我們需要對 Eureka 進行改造,通過集成 Spring-Security 來進行安全認證,加上權限認證來保證安全性。
首先,在 pom.xml 中引入 Spring-Security 的依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
然后在 application.properties 中加上認證的配置信息
spring.security.user.name=javaer123456 #用戶名 spring.security.user.password=123456 #密碼
最后增加Spring Security 配置類
@Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { // 關閉 Spring Security 的 CSRF 驗證(如果不關閉,那么客戶端就連接不上) http.csrf().disable(); // 支持httpBasic http.authorizeRequests().anyRequest().authenticated().and().httpBasic(); } }
這樣我們啟動Eureka Server成功后在訪問 http://localhost:8761/,此時瀏覽器會提示你輸入用戶名和密碼,輸入正確后才能繼續訪問 Eureka 提供的管理頁面。
注意:在 Eureka Server開啟認證后,Eureka Client注冊的配置也要加上認證的用戶名和密碼信息
eureka.client.serviceUrl.defaultZone=http://javaer23456:123456@localhost:8761/eureka/
感謝各位的閱讀,以上就是“什么是Eureka”的內容了,經過本文的學習后,相信大家對什么是Eureka這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。