微服務原則上是應該有多個服務提供者的實例的,在一般狀況下服務提供者的數量和分佈每每是動態變化的,這樣在傳統的單體應用中的那種硬編碼服務url進行遠程調用的方式就不足取。服務註冊中心就是爲了解決服務之間的註冊與發現而產生的。
服務註冊中心本質上是爲了解耦服務提供者和服務消費者。java
服務註冊中心的通常原理:node
Zookeeper它是⼀個分佈式服務框架,是Apache Hadoop 的⼀個⼦項⽬,它主要是⽤來解決分佈式應⽤中常常遇到的⼀些數據管理問題,如:統⼀命名服務、狀態同步服務、集羣管理、分佈式應⽤配置項的管理等。
簡單來講zookeeper本質=存儲+監聽通知。
Zookeeper ⽤來作服務註冊中⼼,主要是由於它具備節點(znode)變動通知功能,只要客戶端監聽相關服務節點,服務節點的全部變動,都能及時的通知到監聽客戶端,這樣做爲調⽤⽅只要使⽤Zookeeper 的客戶端就能實現服務節點的訂閱和變動通知功能了,⾮常⽅便。另外,Zookeeper可⽤性也能夠,由於只要半數以上的選舉節點存活,整個集羣就是可⽤的。git
由Netflix開源,並被Pivatal集成到SpringCloud體系中,它是基於 RestfulAPI ⻛格開發的服務註冊與發現組件。web
Consul是由HashiCorp基於Go語⾔開發的⽀持多數據中⼼分佈式⾼可⽤的服務發佈和註冊服務軟件, 採⽤Raft算法保證服務的⼀致性,且⽀持健康檢查。算法
Nacos是⼀個更易於構建雲原⽣應⽤的動態服務發現、配置管理和服務管理平臺。簡單來講 Nacos就是 註冊中⼼ + 配置中⼼的組合,幫助咱們解決微服務開發必會涉及到的服務註冊與發現,服務配置,服務管理等問題。 Nacos 是 Spring Cloud Alibaba 核⼼組件之⼀,負責服務註冊與發現,還有配置。spring
CAP原理三者對比:
瀏覽器
Eureka 包含兩個組件:Eureka Server 和 Eureka Client, Eureka Client是⼀個Java客戶端,⽤於簡化與Eureka Server的交互; Eureka Server提供服務發現的能⼒,各個微服務啓動時,會經過Eureka Client向Eureka Server 進⾏註冊⾃⼰的信息(例如⽹絡信息),Eureka Server會存儲該服務的信息;
詳細流程以下:緩存
服務提供者向Eureka Server中註冊服務, Eureka Server接受到註冊事件會在集羣和分區中進⾏數據同步,Application Client做爲消費端(服務消費者)能夠從Eureka Server中獲取到服務註冊信息,進⾏服務調⽤。微服務啓動後,會週期性地向Eureka Server發送⼼跳(默認週期爲30秒)以續約⾃⼰的信息服務器
Eureka Server在⼀定時間內沒有接收到某個微服務節點的⼼跳, Eureka Server將會註銷該微服務節點(默認90秒)架構
每一個Eureka Server同時也是Eureka Client,多個Eureka Server之間經過複製的⽅式完成服務註冊列表的同步
Eureka Client會緩存Eureka Server中的信息。即便全部的Eureka Server節點都宕掉,服務消費者依然能夠使⽤緩存中的信息找到服務提供者
下面咱們來分別進行Eureka單實例及集羣環境的搭建及使用(僅列出部分關鍵代碼,詳細代碼請看文末源碼):
新建父工程lagou-parent,在pom.xml中統一規定springcloud的版本:
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Greenwich.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
新建一個子模塊spring-cloud-eureka-server8761,
添加依賴
<!--Eureka server依賴--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency>
在啓動類上面添加@EnableEurekaServer註解,代表此工程爲EurekaServer服務工程。
application.yml:
#eureka server服務端口 server: port: 8761 spring: application: name: lagou-cloud-eureka-server # 應用名稱,應用名稱會在Eureka中做爲服務名稱 # eureka 客戶端配置(和Server交互),Eureka Server 其實也是一個Client eureka: instance: hostname: localhost # 當前eureka實例的主機名 client: service-url: # 配置客戶端所交互的Eureka Server的地址(Eureka Server集羣中每個Server其實相對於其它Server來講都是Client) # 集羣模式下,defaultZone應該指向其它Eureka Server,若是有更多其它Server實例,逗號拼接便可 defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ register-with-eureka: false # ⾃⼰就是服務不須要註冊⾃⼰ 集羣模式下能夠改爲true fetch-registry: false # ⾃⼰就是服務不須要從Eureka Server獲取服務信息,默認爲true,集羣模式下能夠改爲true
執行啓動類,瀏覽器訪問http://localhost:8761/,出現如下界面說明啓動成功。
對界面上的信息進行說明:
至此,單個Eureka server搭建完成。
在上面單體Eureka server的基礎上搭建Eureka集羣。
爲了模擬服務器集羣的效果,修改本機hosts文件:C:\Windows\System32\drivers\etc\hosts
127.0.0.1 LagouCloudEurekaServerA 127.0.0.1 LagouCloudEurekaServerB
在原有工程上新建一個Eureka server模塊,命名爲spring-cloud-eureka-server8762,
spring-cloud-eureka-server8761和spring-cloud-eureka-server8762的application.yml文件以下:
8761:
#eureka server服務端口 server: port: 8761 spring: application: name: lagou-cloud-eureka-server # 應用名稱,應用名稱會在Eureka中做爲服務名稱 # eureka 客戶端配置(和Server交互),Eureka Server 其實也是一個Client eureka: instance: hostname: LagouCloudEurekaServerA # 當前eureka實例的主機名 client: service-url: # 配置客戶端所交互的Eureka Server的地址(Eureka Server集羣中每個Server其實相對於其它Server來講都是Client) # 集羣模式下,defaultZone應該指向其它Eureka Server,若是有更多其它Server實例,逗號拼接便可 defaultZone: http://LagouCloudEurekaServerB:8762/eureka/ register-with-eureka: true # ⾃⼰就是服務不須要註冊⾃⼰ 集羣模式下能夠改爲true fetch-registry: true # ⾃⼰就是服務不須要從Eureka Server獲取服務信息,默認爲true,集羣模式下能夠改爲true
8762:
#eureka server服務端口 server: port: 8762 spring: application: name: lagou-cloud-eureka-server eureka: instance: hostname: LagouCloudEurekaServerB client: service-url: defaultZone: http://LagouCloudEurekaServerA:8761/eureka/ register-with-eureka: true fetch-registry: true
瀏覽器中訪問
http://LagouCloudEurekaServerA:8761/eureka/
及
http://LagouCloudEurekaServerB:8762/eureka/
效果以下:
8761:
8762:
父工程中引入
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-commons</artifactId> </dependency>
服務提供者微服務中引入
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
服務提供者微服務applicaion.yml:
# Eureka配置 eureka: client: service-url: defaultZone: http://LagouCloudEurekaServerA:8761/eureka/,http://LagouCloudEurekaServerB:8762/eureka/ #把 eureka 集羣中的全部 url 都填寫了進來,也能夠只寫⼀臺,由於各個eureka server能夠同步註冊表 instance: prefer-ip-address: true #使⽤ip註冊,不然會使⽤主機名註冊了(此處考慮到對⽼版本的兼容,新版本通過實驗都是ip) #⾃定義實例顯示格式,加上版本號,便於多版本管理,注意是ip-address,早期版本是ipAddress instance-id: ${spring.cloud.client.ipaddress}:${spring.application.name}:${server.port}:@project.version@
服務提供者啓動類添加註解 @EnableDiscoveryClient或@EnableEurekaClient。
說明:
1)從Spring Cloud Edgware版本開始, @EnableDiscoveryClient 或 EnableEurekaClient
可省略。只需加上相關依賴,並進⾏相應配置,便可將微服務註冊到服務發現組件上。
2)@EnableDiscoveryClient和@EnableEurekaClient⼆者的功能是⼀樣的。可是若是選⽤的是eureka服務器,那麼就推薦@EnableEurekaClient,若是是其餘的註冊中⼼,那麼推薦使⽤
@EnableDiscoveryClient,考慮到通⽤性,後期咱們能夠使⽤@EnableDiscoveryClient
啓動EurekaServer,能夠看到服務提供者實例已經成功註冊到EurekaServer上:
註冊服務消費者和服務提供者相似,pom中添加依賴,在啓動類添加@EnableDiscoveryClient,在application.yml中添加eureka的配置信息。
能夠看到服務消費者信息成功註冊到EurekaServer上:
package com.lagou.edu.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import java.util.List; @RestController public class AutoDeliverController { @Autowired private RestTemplate restTemplate; @Autowired private DiscoveryClient discoveryClient; @GetMapping("/checkState/{userId}") public Integer findResumeOpenState(@PathVariable Long userId) { List<ServiceInstance> serviceInstanceList = discoveryClient.getInstances("lagou-service-resume"); ServiceInstance serviceInstance = serviceInstanceList.get(0); String host = serviceInstance.getHost(); int port = serviceInstance.getPort(); String url="http://"+host+":"+port+"/resume/openstate/"+userId; Integer forObject =restTemplate.getForObject(url,Integer.class); System.out.println("======>>>從eureka server獲取服務提供者實例:"+url); return forObject; } }
調用成功信息以下:
源碼地址:eureka-demo 源碼
歡迎訪問個人博客:https://www.liuyj.top