您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關什么是Dive into Eureka,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。
其官方文檔中對自己的定義是:
Eureka is a REST (Representational State Transfer) based service that is primarily used in the AWS cloud for locating services for the purpose of load balancing and failover of middle-tier servers. We call this service, the Eureka Server. Eureka also comes with a Java-based client component,the Eureka Client, which makes interactions with the service much easier. The client also has a built-in load balancer that does basic round-robin load balancing.
簡單來說Eureka就是Netflix開源的一款提供服務注冊和發現的產品,并且提供了相應的Java客戶端。
那么為什么我們在項目中使用了Eureka呢?我大致總結了一下,有以下幾方面的原因:
它提供了完整的Service Registry和Service Discovery實現
首先是提供了完整的實現,并且也經受住了Netflix自己的生產環境考驗,相對使用起來會比較省心。
和Spring Cloud無縫集成
我們的項目本身就使用了Spring Cloud和Spring Boot,同時Spring Cloud還有一套非常完善的開源代碼來整合Eureka,所以使用起來非常方便。
另外,Eureka還支持在我們應用自身的容器中啟動,也就是說我們的應用啟動完之后,既充當了Eureka的角色,同時也是服務的提供者。這樣就極大的提高了服務的可用性。
Open Source
最后一點是開源,由于代碼是開源的,所以非常便于我們了解它的實現原理和排查問題。
相信大家看到這里,已經對Eureka有了一個初步的認識,接下來我們就來深入了解下它吧~
上圖簡要描述了Eureka的基本架構,由3個角色組成:
Eureka Server
提供服務注冊和發現
Service Provider
服務提供方
將自身服務注冊到Eureka,從而使服務消費方能夠找到
Service Consumer
服務消費方
從Eureka獲取注冊服務列表,從而能夠消費服務
需要注意的是,上圖中的3個角色都是邏輯角色。在實際運行中,這幾個角色甚至可以是同一個實例,比如在我們項目中,Eureka Server和Service Provider就是同一個JVM進程。
上圖更進一步的展示了3個角色之間的交互。
Service Provider會向Eureka Server做Register(服務注冊)、Renew(服務續約)、Cancel(服務下線)等操作。
Eureka Server之間會做注冊服務的同步,從而保證狀態一致
Service Consumer會向Eureka Server獲取注冊服務列表,并消費服務
為了給大家一個更直觀的印象,我們可以通過一個簡單的demo來實際運行一下,從而對Eureka有更好的了解。
Git倉庫:git@github.com:nobodyiam/spring-cloud-in-action.git
這個項目使用了Spring Cloud相關類庫,包括:
Spring Cloud Config
Spring Cloud Eureka (Netflix)
Demo項目使用了Spring Cloud Config做配置,所以第一步先在本地啟動Config Server。
由于項目基于Spring Boot開發,所以直接運行com.nobodyiam.spring.cloud.in.action.config.ConfigServerApplication
即可。
Eureka Server的Demo模塊名是:eureka-server
。
eureka-server
是一個基于Spring Boot的Web應用,我們首先需要做的就是在pom中引入Spring Cloud Eureka Server的依賴。
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> <version>1.1.0.RC2</version> </dependency>
啟用Eureka Server非常簡單,只需要加上@EnableEurekaServer
即可。
@EnableEurekaServer @SpringBootApplication public class EurekaServiceApplication { public static void main(String[] args) { SpringApplication.run(EurekaServiceApplication.class, args); } }
做完以上配置后,啟動應用,Eureka Server就開始工作了!
啟動完,打開http://localhost:8761就能看到啟動成功的畫面了。
Service Provider的Demo模塊名是:reservation-service
。
Service Consumer的Demo模塊名是:reservation-client
。
reservation-service
和reservation-client
都是基于Spring Boot的Web應用,我們首先需要做的就是在pom中引入Spring Cloud Eureka的依賴。
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> <version>1.1.0.RC2</version> </dependency>
啟用Service Provider非常簡單,只需要加上@EnableDiscoveryClient
即可。
@EnableDiscoveryClient @SpringBootApplication public class ReservationServiceApplication { public static void main(String[] args) { new SpringApplicationBuilder(ReservationServiceApplication.class) .run(args); } }
做完以上配置后,啟動應用,Server Provider就開始工作了!
啟動完,打開http://localhost:8761就能看到服務已經注冊到Eureka Server了。
啟動Service Consumer其實和Service Provider一樣,因為本質上Eureka提供的客戶端是不區分Provider和Consumer的,一般情況下,Provider同時也會是Consumer。
@EnableDiscoveryClient @SpringBootApplication public class ReservationClientApplication { @Bean CommandLineRunner runner(DiscoveryClient dc) { return args -> { dc.getInstances("reservation-service") .forEach(si -> System.out.println(String.format( "Found %s %s:%s", si.getServiceId(), si.getHost(), si.getPort()))); }; } public static void main(String[] args) { SpringApplication.run(ReservationClientApplication.class, args); } }
上述代碼中通過dc.getInstances("reservation-service")
就能獲取到當前所有注冊的reservation-service
服務。
看了前面的demo,我們已經初步領略到了Spring Cloud和Eureka的強大之處,通過短短幾行配置就實現了服務注冊和發現!
相信大家一定想了解Eureka是如何實現的吧,所以接下來我們繼續Dive!首先來看下Eureka Server的幾個對外接口實現。
首先來看Register(服務注冊),這個接口會在Service Provider啟動時被調用來實現服務注冊。同時,當Service Provider的服務狀態發生變化時(如自身檢測認為Down的時候),也會調用來更新服務狀態。
接口實現比較簡單,如下圖所示。
ApplicationResource
類接收Http服務請求,調用PeerAwareInstanceRegistryImpl
的register
方法
PeerAwareInstanceRegistryImpl
完成服務注冊后,調用replicateToPeers
向其它Eureka Server節點(Peer)做狀態同步
注冊的服務列表保存在一個嵌套的hash map中:
第一層hash map的key是app name,也就是應用名字
第二層hash map的key是instance name,也就是實例名字
以3.2.4.2中的截圖為例,RESERVATION-SERVICE
就是app name,jason-mbp.lan:reservation-service:8000
就是instance name。
Hash map定義如下:
private final ConcurrentHashMap<String, Map<String, Lease<InstanceInfo>>> registry = new ConcurrentHashMap<String, Map<String, Lease<InstanceInfo>>>();
Renew(服務續約)操作由Service Provider定期調用,類似于heartbeat。主要是用來告訴Eureka Server Service Provider還活著,避免服務被剔除掉。接口實現如下圖所示。
可以看到,接口實現方式和register
基本一致:首先更新自身狀態,再同步到其它Peer。
Fetch Registries由Service Consumer調用,用來獲取Eureka Server上注冊的服務。
為了提高性能,服務列表在Eureka Server會緩存一份,同時每30秒更新一次。
在前面的Register、Renew、Cancel接口實現中,我們看到了都會有replicateToPeers操作,這個就是用來做Peer之間的狀態同步。
通過這種方式,Service Provider只需要通知到任意一個Eureka Server后就能保證狀態會在所有的Eureka Server中得到更新。
具體實現方式其實很簡單,就是接收到Service Provider請求的Eureka Server,把請求再次轉發到其它的Eureka Server,調用同樣的接口,傳入同樣的參數,除了會在header中標記isReplication=true,從而避免重復的replicate。
那大家可能會有疑問,Eureka Server是怎么知道有多少Peer的呢?
Eureka Server在啟動后會調用EurekaClientConfig.getEurekaServerServiceUrls
來獲取所有的Peer節點,并且會定期更新。定期更新頻率可以通過eureka.server.peerEurekaNodesUpdateIntervalMs
配置。
這個方法的默認實現是從配置文件讀取,所以如果Eureka Server節點相對固定的話,可以通過在配置文件中配置來實現。
如果希望能更靈活的控制Eureka Server節點,比如動態擴容/縮容,那么可以override getEurekaServerServiceUrls
方法,提供自己的實現,比如我們的項目中會通過數據庫讀取Eureka Server列表。
具體實現如下圖所示:
現在來看下Service Provider的實現細節,主要就是Register、Renew、Cancel這3個操作。
Service Provider要對外提供服務,一個很重要的步驟就是把自己注冊到Eureka Server上。
這部分的實現比較簡單,只需要在啟動時和實例狀態變化時調用Eureka Server的接口注冊即可。需要注意的是,需要確保配置eureka.client.registerWithEureka
=true。
在Service Provider服務shut down的時候,需要及時通知Eureka Server把自己剔除,從而避免客戶端調用已經下線的服務。
邏輯本身比較簡單,通過對方法標記@PreDestroy
,從而在服務shut down的時候會被觸發。
Service Consumer這塊的實現相對就簡單一些,因為它只涉及到從Eureka Server獲取服務列表和更新服務列表。
Service Consumer在啟動時會從Eureka Server獲取所有服務列表,并在本地緩存。需要注意的是,需要確保配置eureka.client.shouldFetchRegistry
=true。
Service Consumer和Service Provider一樣,也有一個如何知道Eureka Server地址的問題。
其實由于Service Consumer和Service Provider本質上使用的是同一個Eureka客戶端,所以這部分邏輯是一樣的,這里就不再贅述了。
關于什么是Dive into Eureka就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。