您好,登錄后才能下訂單哦!
本篇文章為大家展示了SpringColud Eureka服務注冊與發現的示例分析,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
本文中所有代碼都會上傳到git上,請放心瀏覽項目git地址:https://github.com/839022478/Spring-Cloud
在傳統應用中,組件之間的調用,通過有規范的約束的接口來實現,從而實現不同模塊間良好的協作。但是被拆分成微服務后,每個微服務實例的網絡地址都可能動態變化,數量也會變化,使得原來硬編碼的地址失去了作用。需要一個中心化的組件來進行服務的登記和管理,為了解決上面的問題,于是出現了服務治理,就是管理所有的服務信息和狀態,也就是我們所說的注冊中心
比如我們去做火車或者汽車,需要去買票乘車,只看我們有沒有票(有沒有服務),有就去買票(獲取注冊列表),然后乘車(調用),不用關心到底有多少車在運行
流程圖:
使用注冊中心,我們不需要關心有多少提供方,只管去調用就可以了,那么注冊中心有哪些呢?
注冊中心:Eureka,Nacos,Consul,Zookeeper
本文中講解的是比較火熱的Spring Cloud微服務下的Eureka,Eureka是Netflix開發的服務發現框架,是一個RESTful風格的服務,是一個用于服務發現和注冊的基礎組件,是搭建Spring Cloud微服務的前提之一,它屏蔽了Server和client的交互細節,使得開發者將精力放到業務上。
服務注冊與發現主要包括兩個部分:服務端(EurekaServer)和客戶端(EurekaClient)
服務端(Eureka Server): 一個公共服務,為Client提供服務注冊和發現的功能,維護注冊到自身的Client的相關信息,同時提供接口給Client獲取注冊表中其他服務的信息,使得動態變化的Client能夠進行服務間的相互調用。
客戶端(Eureka Client): Client將自己的服務信息通過一定的方式登記到Server上,并在正常范圍內維護自己信息一致性,方便其他服務發現自己,同時可以通過Server獲取到自己依賴的其他服務信息,完成服務調用,還內置了負載均衡器,用來進行基本的負載均衡
Eureka GIt官網:https://github.com/Netflix/Eureka
服務注冊與發現關系圖:
1.3.1 client功能
鴻蒙官方戰略合作共建——HarmonyOS技術社區
注冊:每個微服務啟動時,將自己的網絡地址等信息注冊到注冊中心,注冊中心會存儲(內存中)這些信息。
獲取服務注冊表:服務消費者從注冊中心,查詢服務提供者的網絡地址,并使用該地址調用服務提供者,為了避免每次都查注冊表信息,所以client會定時去server拉取注冊表信息到緩存到client本地。
心跳:各個微服務與注冊中心通過某種機制(心跳)通信,若注冊中心長時間和服務間沒有通信,就會注銷該實例。
調用:實際的服務調用,通過注冊表,解析服務名和具體地址的對應關系,找到具體服務的地址,進行實際調用。
1.3.2 server注冊中心功能
鴻蒙官方戰略合作共建——HarmonyOS技術社區
服務注冊表:記錄各個微服務信息,例如服務名稱,ip,端口等。注冊表提供 查詢API(查詢可用的微服務實例)和管理API(用于服務的注冊和注銷)。
服務注冊與發現:注冊:將微服務信息注冊到注冊中心。發現:查詢可用微服務列表及其網絡地址。
服務檢查:定時檢測已注冊的服務,如發現某實例長時間無法訪問,就從注冊表中移除。
在有的教程中,會引入 spring-boot-starter-web,這個依賴其實不用,因為 spring-cloud-starter-netflix-eureka-server的依賴已經包含了它,在pom依賴進去,就可以了
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency>
server: port: 8500 eureka: client: #是否將自己注冊到Eureka Server,默認為true,由于當前就是server,故而設置成false,表明該服務不會向eureka注冊自己的信息 register-with-eureka: false #是否從eureka server獲取注冊信息,由于單節點,不需要同步其他節點數據,用false fetch-registry: false #設置服務注冊中心的URL,用于client和server端交流 service-url: defaultZone: http://localhost:8080/eureka/
啟動類上添加此注解標識該服務為配置中心@EnableEurekaServer
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @EnableEurekaServer @SpringBootApplication public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } }
我們啟動 EurekaDemoApplication,然后在瀏覽器中輸入地址 http://localhost:8500/,就可以啟動我們的 Eureka 了,我們來看下效果,出現了這個畫面,就說明我們已經成功啟動~,只是此時我們的服務中是還沒有客戶端進行注冊
注意:在客戶端pom里面我們需要加上 spring-boot-starter-web,否則服務是無法正常啟動的
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
#注冊中心 eureka: client: #設置服務注冊中心的URL service-url: defaultZone: http://localhost:8500/eureka/ #服務名 instance: appname: mxn
在客戶端啟動類中我們需要加上 @EnableDiscoveryClient
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @EnableDiscoveryClient @SpringBootApplication public class EurekaClientApplication { public static void main(String[] args) { SpringApplication.run(EurekaClientApplication.class, args); } }
工程啟動后,刷新 http://localhost:8500/頁面,我們可以發現服務注冊成功了
并且我們可以在idea日志打印中看到
DiscoveryClient_MXN/DESKTOP-5BQ3UK8-registration status:204
說明就是注冊成功了 Eureka Server與Eureka Client之間的聯系主要通過心跳的方式實現。心跳(Heartbeat)即Eureka Client定時向Eureka Server匯報本服務實例當前的狀態,維護本服務實例在注冊表中租約的有效性。
Eureka Client將定時從Eureka Server中拉取注冊表中的信息,并將這些信息緩存到本地,用于服務發現
官網地址:https://github.com/Netflix/eureka/wiki/Eureka-REST-operations
Eureka服務器還提供了一個端點 (eureka/apps/{applicaitonName})可以查看所注冊的服務詳細信息 。applicaitonName就是微服務的名稱,比如這里我們訪問 http://localhost:8500/eureka/apps/mxn
存儲了每個客戶端的注冊信息。EurekaClient從EurekaServer同步獲取服務注冊列表。通過一定的規則選擇一個服務進行調用
服務提供者: 是一個eureka client,向Eureka Server注冊和更新自己的信息,同時能從Eureka Server注冊表中獲取到其他服務的信息。
服務注冊中心: 提供服務注冊和發現的功能。每個Eureka Cient向Eureka Server注冊自己的信息,也可以通過Eureka Server獲取到其他服務的信息達到發現和調用其他服務的目的。
服務消費者: 是一個eureka client,通過Eureka Server獲取注冊到其上其他服務的信息,從而根據信息找到所需的服務發起遠程調用。
同步復制: Eureka Server之間注冊表信息的同步復制,使Eureka Server集群中不同注冊表中服務實例信息保持一致。
遠程調用: 服務客戶端之間的遠程調用。
注冊: Client端向Server端注冊自身的元數據以供服務發現。
續約: 通過發送心跳到Server以維持和更新注冊表中服務實例元數據的有效性。當在一定時長內,Server沒有收到Client的心跳信息,將默認服務下線,會把服務實例的信息從注冊表中刪除。
下線: Client在關閉時主動向Server注銷服務實例元數據,這時Client的服務實例數據將從Server的注冊表中刪除。
獲取注冊表: Client向Server請求注冊表信息,用于服務發現,從而發起服務間遠程調用。
有時候我們會看到這樣的提示信息:
EMERGENCY!EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.
這是因為默認情況下,Eureka Server在一定時間內,沒有接收到某個微服務心跳,會將某個微服務注銷(90S)。但是當網絡故障時,微服務與Server之間無法正常通信,上述行為就非常危險,因為微服務正常,不應該注銷,它的指導思想就是 寧可保留健康的和不健康的,也不盲目注銷任何健康的服務我們也可以通過命令去關閉自我保護的功能:
eureka: server: enable-self-preservation: false
那么自我保護是如何觸發的呢?
自我保護機制的觸發條件是: 當每分鐘心跳次數( renewsLastMin) 小于 numberOfRenewsPerMinThreshold時, 并且開啟自動保護模式開關( eureka.server.enable-self-preservation=true) 時 觸發自我保護機制,不再自動過期租約 上面我們所有的小于 numberOfRenewsPerMinThreshold,到底是怎么計算的呢, 我們在eureka源碼中可以得知: numberOfRenewsPerMinThreshold = expectedNumberOfRenewsPerMin * 續租百分比(默認為0.85) expectedNumberOfRenewsPerMin = 當前注冊的應用實例數 x 2 當前注冊的應用實例數 x 2 是因為,在默認情況下,注冊的應用實例每半分鐘續租一次,那么一分鐘心跳兩次,因此 x 2
例如:我們有10個服務,期望每分鐘續約數:10 * 2=20,期望閾值:20*0.85=17,當少于17時,就會觸發自我保護機制
由于server和client通過心跳保持 服務狀態,而只有狀態為UP的服務才能被訪問。看eureka界面中的status。
比如心跳一直正常,服務一直UP,但是此服務DB(數據庫)連不上了,無法正常提供服務。
此時,我們需要將 微服務的健康狀態也同步到server。只需要啟動eureka的健康檢查就行。這樣微服務就會將自己的健康狀態同步到eureka。配置如下即可。
在client端配置:將自己的健康狀態傳播到server。
eureka: client: healthcheck: enabled: true
import com.netflix.appinfo.InstanceInfo; import org.springframework.cloud.netflix.eureka.server.event.*; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; import java.time.LocalDateTime; @Component public class CustomEvent { @EventListener public void listen(EurekaInstanceCanceledEvent event ) { System.out.println(LocalDateTime.now()+"服務下線事件:"+event.getAppName()+"---"+event.getServerId()); //發釘釘 } @EventListener public void listen(EurekaInstanceRegisteredEvent event) { InstanceInfo instanceInfo = event.getInstanceInfo(); System.out.println(LocalDateTime.now()+"服務上線事件:"+instanceInfo.getAppName()+"---"+instanceInfo.getInstanceId()); } @EventListener public void listen(EurekaInstanceRenewedEvent event) { System.out.println(LocalDateTime.now()+"服務續約/心跳上報事件:"+event.getAppName()+"---"+event.getServerId()); } @EventListener public void listen(EurekaRegistryAvailableEvent event) { System.out.println(LocalDateTime.now()+"注冊中心可用事件"); } @EventListener public void listen(EurekaServerStartedEvent event) { System.out.println(LocalDateTime.now()+"注冊中心啟動事件"); } }
Eureka Client 會每隔 30 秒發送一次心跳來續約。通過續約來告知 Eureka Server 該 Eureka Client 運行正常,沒有出現問題。默認情況下,如果 Eureka Server 在 90 秒內沒有收到 Eureka Client 的續約,Server 端會將實例從其注冊表中刪除,此時間可配置,一般情況不建議更改。
如果Eureka Client在注冊后,既沒有續約,也沒有下線(服務崩潰或者網絡異常等原因),那么服務的狀態就處于不可知的狀態,不能保證能夠從該服務實例中獲取到回饋,所以需要服務剔除此方法定時清理這些不穩定的服務,該方法會批量將注冊表中所有過期租約剔除,剔除是定時任務,默認60秒執行一次。延時60秒,間隔60秒
剔除的限制:1.自我保護期間不清除。2.分批次清除。
由于集群間的同步復制是通過HTTP的方式進行,基于網絡的不可靠性,集群中的Eureka Server間的注冊表信息難免存在不同步的時間節點,不滿足CAP中的C(數據一致性)
中間我們講解了eureka的節點搭建,以及原理,對于現在很火熱的微服務,我們對Eureka是非常有必要進行了解的。
上述內容就是SpringColud Eureka服務注冊與發現的示例分析,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。