⒈Eureka是什么?
Eureka是Netflix的一個子模塊,也是核心模塊之一,Eureka是一個基於REST的服務,用於定位服務以實現雲端中間層服務發現和故障轉移,服務注冊與發現對於微服務架構來說是非常重要的,有了服務注冊與發現,只需要使用服務的標識符就可以訪問到服務,而不需要修改服務調用的配置文件,功能類似於Dubbo的注冊中心,例如Zookeeper。
SpringCloud封裝了Netflix公司開發的Eureka模塊來實現服務注冊與發現,Eureka采用了C/S設計架構,Eureka Server作為服務注冊功能的服務器,它是服務注冊中心。而系統中的其他微服務,使用Eureka Client連接到Eureka Server並維持心跳連接,這樣系統的維護人員就可以通過Eureka Server來監控系統中的各個微服務是否正常運行,SpringCloud的一些其他模塊(例如Zuul)就可以通過Eureka Server來發現系統中的其他微服務,並執行相關的邏輯。
Eureka包含兩個組件,Eureka Server和Eureka Client。
Eureka Server提供服務注冊服務。各個微服務啟動后,會在Eureka Server中進行注冊,這樣Eureka Server中的服務注冊表中將會存儲所有可用服務節點的信息,服務節點的信息可以在界面中直觀的看到。
Eureka Client是一個Java客戶端,用於簡化Eureka Server的交互,客戶端同時也具備一個內置的-使用輪詢(round-robin)負載算法的負載均衡器。在應用啟動后,Eureka Client將會向Eureka Server發送心跳(默認周期30秒),如果Eureka Server在多個心跳周期內沒有接收到某個節點的心跳,Eureka Server將會從服務的注冊列表中移除該服務節點(默認90秒)。
⒉Eureka三大角色
①Eureka Server - 提供服務注冊與發現
②Service Provider(服務提供者) - 將自身服務注冊到Eureka Server,從而使服務消費者能夠找到。
③Service Consumer(服務消費者) - 從Eureka Server中獲取服務列表,從而能夠消費服務。
⒊示例
請訪問我的示例文章地址:https://www.cnblogs.com/fanqisoft/p/10357598.html
⒋一些Eureka配置擴展
①修改在Eureka管理界面中的主機名稱
1 eureka: 2 instance: 3 instance-id: #設置主機名稱
②修改在Eureka管理界面中的主機ip是否顯示
1 eureka: 2 instance: 3 prefer-ip-address: true #主機ip是否顯示
③修改在Eureka管理界面中的主機info詳細信息
ⅰ添加pom依賴
1 <dependency> 2 <groupId>org.springframework.boot</groupId> 3 <artifactId>spring-boot-starter-actuator</artifactId> 4 </dependency>
ⅱ父工程pom文件中添加構建的Build信息(可選)
ⅲ在配置文件中添加info配置信息
⒌Eureka自我保護
①導致原因:
某時刻某一個微服務不可用了,Eureka不會立刻清理,依舊會對該微服務的信息進行保存。
②什么是自我保護模式?
默認情況下,如果Eureka Server在一定時間內沒有收到某個微服務實例的心跳,Eureka Server將會注銷該實例(默認90秒),但是當網絡分區故障發生時,微服務與Eureka Server之間無法正常通信,那么以上的行為可能就變得非常危險了,因為這個微服務本身其實是健康的,此時不應該注銷這個微服務。
Eureka通過“自我保護模式”來解決這個問題,當Eureka Server節點在短時間內丟失過多客戶端時(可能這些客戶端發生了網絡分區故障),那么當前Eureka Server節點就會進入自我保護模式,一旦進入該模式,Eureka Server就會保護服務注冊表中的信息,不再刪除服務注冊表中的數據,也就是說不會注銷任何微服務,當網絡故障恢復后,該Eureka Server節點就會自動退出自我保護模式。
在自我保護模式中,Eureka Server會保護服務注冊表中的信息,不會注銷任何服務實例,當它收到的心跳數重新恢復到閾值以上時,該Eureka Server節點就會自動退出自我保護模式,它的設計哲學就是寧可保留錯誤的服務注冊信息,也不盲目注銷任何可能健康的服務實例。
自我保護模式是一種應對網絡異常的安全保護措施,它的架構哲學是寧可同時保留所有微服務(健康的微服務和不健康的微服務都會保留)也不盲目注銷任何可能健康的微服務。使用自我保護模式,可以讓Eureka集群更加健壯、穩定。
在SpringCloud中,可以使用eureka.server.enable-self-preservation=false來禁用自我保護模式(不推薦)。
⒍Eureka服務發現
①在服務消費者主程序啟動類上添加@EnableDiscoveryClient注解
1 package cn.coreqi; 2 3 import org.springframework.boot.SpringApplication; 4 import org.springframework.boot.autoconfigure.SpringBootApplication; 5 import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 6 import org.springframework.cloud.client.loadbalancer.LoadBalanced; 7 import org.springframework.cloud.netflix.eureka.EnableEurekaClient; 8 import org.springframework.context.annotation.Bean; 9 import org.springframework.web.client.RestOperations; 10 import org.springframework.web.client.RestTemplate; 11 12 @SpringBootApplication 13 //@EnableDiscoveryClient //開啟服務發現功能 14 @EnableDiscoveryClient //開啟服務發現功能 15 public class SpringbootcloudserviceconsumerApplication { 16 17 public static void main(String[] args) { 18 SpringApplication.run(SpringbootcloudserviceconsumerApplication.class, args); 19 } 20 21 @Bean 22 @LoadBalanced //使用負載均衡機制 23 public RestOperations restTemplate(){ 24 return new RestTemplate(); 25 } 26 27 }
②控制器添加相關代碼
1 package cn.coreqi.controller; 2 3 import cn.coreqi.entities.User; 4 import org.springframework.beans.factory.annotation.Autowired; 5 import org.springframework.cloud.client.ServiceInstance; 6 import org.springframework.cloud.client.discovery.DiscoveryClient; 7 import org.springframework.web.bind.annotation.GetMapping; 8 import org.springframework.web.bind.annotation.RestController; 9 import org.springframework.web.client.RestOperations; 10 import java.util.List; 11 12 @RestController 13 public class UserController { 14 @Autowired 15 private RestOperations restTemplate; 16 17 @Autowired 18 private DiscoveryClient client; 19 20 @GetMapping("/userno2") 21 public String discovery(){ 22 List<String> list = client.getServices(); 23 System.out.println("*****" + list); 24 List<ServiceInstance> serviceList = client.getInstances("USER-PROVIDER"); 25 for (ServiceInstance item : serviceList){ 26 System.out.println(item.getServiceId() + "\t" + item.getHost() + "\t" + item.getPort() + "\t" + item.getUri()); 27 } 28 return "success"; 29 } 30 31 @GetMapping("/userno1") 32 public User getUsersFirst(){ 33 User[] users = restTemplate.getForObject("http://user-provider/users",User[].class); 34 return users[0]; 35 } 36 }
⒎Eureka集群配置
為了更直觀的顯示集群效果,做了一下域名關系映射。
①Eureka Server集群搭建
Ⅰ新建幾個Eureka Server項目(略)
Ⅱ在這幾個Eureka Server項目的主程序啟動類上添加@EnableEurekaServer注解(以一個為例)
1 package cn.coreqi; 2 3 import org.springframework.boot.SpringApplication; 4 import org.springframework.boot.autoconfigure.SpringBootApplication; 5 import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; 6 7 @SpringBootApplication 8 @EnableEurekaServer 9 public class EurekaServerApplication { 10 11 public static void main(String[] args) { 12 SpringApplication.run(EurekaServerApplication.class, args); 13 } 14 15 }
Ⅲ分別修改它們的配置文件(以兩個為例)
1 server: 2 port: 8761 3 eureka: 4 instance: 5 hostname: eureka-server1 #Eureka服務端實例名稱 6 client: 7 register-with-eureka: false #是否向注冊中心注冊自己 8 fetch-registry: false #是否從Eureka上獲取服務的注冊信息,自己就是注冊中心,本身職責就是維護服務實例,並不需要去檢索服務 9 service-url: 10 defaultZone: http://eureka8762.com:8762/eureka/,http://eureka8763.com:8763/eureka/ #設置與Eureka Server交互的地址(查詢服務、注冊服務等)
1 server: 2 port: 8762 3 eureka: 4 instance: 5 hostname: eureka-server2 #Eureka服務端實例名稱 6 client: 7 register-with-eureka: false #是否向注冊中心注冊自己 8 fetch-registry: false #是否從Eureka上獲取服務的注冊信息,自己就是注冊中心,本身職責就是維護服務實例,並不需要去檢索服務 9 service-url: 10 defaultZone: http://eureka8761.com:8761/eureka/,http://eureka8763.com:8763/eureka/ #設置與Eureka Server交互的地址(查詢服務、注冊服務等)
總結一下不同:
1.端口不同
2.eureka.instance.hostname 不可重名
3.eureka.client.service-url.defaultZone 手牽手模式,把除自己以外的集群內的其它Eureka Server全部配置進來
②Eureka Client連接Eureka Server集群
Ⅰ新建一個Eureka Client項目用作服務提供者(必須引入Web模塊,否則注冊服務后項目會自動停止)
1 <dependency> 2 <groupId>org.springframework.cloud</groupId> 3 <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> 4 </dependency> 5 <dependency> 6 <groupId>org.springframework.boot</groupId> 7 <artifactId>spring-boot-starter-web</artifactId> 8 </dependency>
Ⅱ在主程序啟動類上添加@EnableEurekaClient注解
1 package cn.coreqi; 2 3 import org.springframework.boot.SpringApplication; 4 import org.springframework.boot.autoconfigure.SpringBootApplication; 5 import org.springframework.cloud.netflix.eureka.EnableEurekaClient; 6 7 @SpringBootApplication 8 @EnableEurekaClient 9 public class ServiceProviderApplication { 10 11 public static void main(String[] args) { 12 SpringApplication.run(ServiceProviderApplication.class, args); 13 } 14 15 }
Ⅲ修改配置文件
1 server: 2 port: 8001 3 spring: 4 application: 5 name: user-provider 6 eureka: 7 instance: 8 prefer-ip-address: true #注冊服務的時候使用服務的ip地址 9 client: 10 service-url: 11 defaultZone: http://eureka8761.com:8761/eureka/,http://eureka8762.com:8762/eureka/,http://eureka8763.com:8763/eureka/
總結一下:
1.eureka.client.service-url.defaultZone:將集群內所有的Eureka Server全部配置進來
⒏數據的有關擴展
傳統的關系型數據庫(SqlServer、MySQL、Oracle) =》 ACID
非關系型數據庫(Redis、MongDB) =》 CAP
ACID:
A(Atomicity)原子性:事務中的所有操作要么都成功執行,要么什么都不做。
C(Consistency)一致性:數據庫要一直處於一致的狀態,事務的運行不會改變數據庫原本的一致性約束。
I(Isolation)獨立性:並發的事務之間不會相互影響。
D(Durability)持久性:一旦事務提交,它所做的修改將會永久的保存在數據庫上,即使宕機也不會丟失。
CAP:
C(Consistency)強一致性
A(Availability)可用性
P(Partition tolevance)分區容錯性
CAP的3進2原則:即任何一個分布式系統不可能同時滿足CAP,只能3選2。
CA:單點集群,滿足一致性、可用性的系統,通常在可擴展性上不太強大。
CP:滿足一致性、分區容忍性的系統,通常性能不是特別高。
AP:滿足可用性、分區容忍性的系統,通常可能對一致性要求低一些。
因為當前的網絡硬件肯定會出現延遲丟包等問題,因此,分布式系統中,分區容忍性(P)是我們必須要實現的,所以我們只能在一致性(CP)和可用性(AP)之間權衡。
天貓雙11保證的是AP原則。
Zookeeper保證CP
當向注冊中心查詢服務列表時,我們可以容忍注冊中心返回的是幾分鍾以前的注冊信息,但不能接受服務直接Down掉不可用,也就是說,服務注冊功能對可用性的要求要高於一致性,但是Zookeeper會出現這樣一種情況,當主節點(master)因為網絡故障與其它節點失去聯系時,剩余節點將會重新進行主節點的選舉,選舉的時間太長,一般在30s~120s之間,且選舉的過程中整個Zookeeper集群都是不可用的,這就導致了在選舉期間Zookeeper的注冊服務是癱瘓的。
在雲部署的環境下,因網絡問題使得Zookeeper集群失去主節點(master)是較大概率會發生的事情,雖然服務能夠最終恢復,但是漫長的選舉時間導致注冊服務長時間不可用是不能容忍的。
Eureka保證AP
Eureka在設計時就優先保證了可用性,Eureka各個節點都是平等的,無論多少個節點掛掉都不會影響正常工作的節點,剩余的節點依然可以提供服務注冊和查詢,而Eureka Client在向某個Eureka Server注冊時如果發現連接失敗,則會自動切換至其它節點,只要有一台Eureka Server還在,就能保證注冊服務可用(可用性),只不過查到的信息可能不是最新的(不保證強一致性)。除此之外,Eureka還有一種自我保護機制,如果在15分鍾內超過85%的節點都沒有正常的心跳,那么Eureka就認為客戶端與注冊中心之間出現了網路故障,此時會出現以下幾種情況:
1.Eureka不再從注冊列表中移除因為長時間沒收到心跳而應該過期的服務。
2.Eureka仍然能夠接收新服務的注冊和查詢請求,但是不會被同步到其它節點上(即保證當前節點依然可用)。
3.當網絡穩定時,當前實例新的注冊信息會被同步到其它節點中。
因此,Eureka可以很大的應對因網絡故障導致部分節點失去聯系的情況,而不會像Zookeeper那樣使整個注冊服務癱瘓。