前言
上一節通過RestTemplate實現了生產者與消費者之間的調用關係,也提到了這種方式在分佈式架構中是存在着問題的。
例如:商品微服務是消費者的同時還是其他服務的生產者,那麼他們的調用配置都需要變更。當然可以採用nginx等反向代理來實現,但是當有數百個微服務豈不是被搞si了。針對這個問題引出了服務發現的概念,如下圖所示:
服務發現機制:
1、服務生產者和服務消費者在啓動的時候都會把自己的網絡地址(IP+端口)註冊到服務發現組件,服務消費者要調用的時候先到服務發現組件裏面查詢服務提供者的IP+端口然後進行調用。
2、任何服務都有宕掉的可能,如果服務生產者掛了那就需要將服務發現組件裏註冊的對應節點剔除掉,所以當服務消費者和生產者註冊到服務發現組件後就會隔段時間發起心跳,如果接受不到節點信息就剔除掉。
服務發現組件功能
1、服務註冊表
可以將服務註冊表看做是數據庫,因爲本身就是將當前可用服務示例的網絡信息(IP+端口)記錄下來。提供查詢API和管理API,使用查詢API可以獲得可用的服務示例,使用管理API實現註冊和註銷;
2、服務註冊
將網絡信息(IP+端口)存放到服務註冊表。
3、健康檢查
上面提到的心跳檢查就是其中一個功能,將不可用的網絡信息進行剔除,保證服務消費者能夠調用到正常的網絡信息。
服務發現的方式
1、客戶端發現
例如:Eureka、zookeeper等。
2、服務器端發現
例如:Consul + nginx
Eureka簡介
Eureka是Netflix開發的服務發現框架,本身是一個基於REST的服務,主要用於定位運行在AWS域中的中間層服務,以達到負載均衡和中間層服務故障轉義的目的。Spring Cloud將它集成在其子項目spring-cloud-netflix中,用來實現Spring Cloud的服務發現功能。
實現一個Eureka Server
第一步:添加Eureka依賴(pom.xml)
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
第二步:Spring Boot啓動類增加註解
/**
* @Auther: Lin
* @Date: 2019-07-29 23:01
* @Description: 使用Eureka做服務發現
*/
@SpringBootApplication
@EnableEurekaServer
public class MicroserviceDiscoveryEurekaApplication {
public static void main(String[] args){
SpringApplication.run(MicroserviceDiscoveryEurekaApplication.class,args);
}
}
第三步:增加Eureka配置(application.ml)
server:
port: 8761
eureka:
client:
# 是否要註冊到其他Eureka Server實例
register-with-eureka: false
# 是否要從其他Eureka Server實例獲取數據
fetch-registry: false
service-url:
defaultZone: http://127.0.0.1:8761/eureka/
備註:Eureka默認端口爲8761。
第四步:啓動測試
訪問地址:http://127.0.0.1:8761,如下圖所示:
出現上面控制檯頁面說明Eureka單機部署成功。
將用戶(user)和商品(goods)服務註冊到Eureka Service
基於SpringCloud實戰(一)中的microservice-consumer-goods和microservice-provider-user微服務,將服務註冊到Eureka Service。
第一步:添加Eureka Client依賴(pom.xml)
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
備註:goods和user兩個工程pom.xml都需添加
第二步:添加註解
#microservice-provider-user 微服務
@SpringBootApplication
#@EnableEurekaClient
public class MicroserviceProviderUserApplication {
public static void main(String[] args) {
SpringApplication.run(MicroserviceProviderUserApplication.class, args);
}
}
#microservice-consumer-goods 微服務
@SpringBootApplication
#@EnableEurekaClient
public class MicroserviceDiscoveryEurekaApplication {
public static void main(String[] args) {
SpringApplication.run(MicroserviceDiscoveryEurekaApplication, args);
}
}
備註:Spring Cloud 的Edgware版本之前客戶端啓動類需要增加@EnableDiscoveryClient或 @EnableEurekaClient,從Edgware開始,可省略
第三步:添加配置
#microservice-provider-user 微服務
spring:
application:
# 指定註冊到eureka server上的服務名稱
name: microservice-provider-user
eureka:
client:
service-url:
# eureka server的通訊地址,注意路徑
defaultZone: http://127.0.0.1:8761/eureka/
instance:
# 是否將IP註冊到eureka server,false:否,ture:是
prefer-ip-address: true
#microservice-consumer-goods 微服務
spring:
application:
# 指定註冊到eureka server上的服務名稱
name: microservice-consumer-goods
eureka:
client:
service-url:
# eureka server的通訊地址,注意路徑
defaultZone: http://127.0.0.1:8761/eureka/
instance:
# 是否將IP註冊到eureka server,false:否,ture:是
prefer-ip-address: true
第四步:啓動測試
- 按照順序啓動Eureka Server、用戶微服務和商品微服務;
- 訪問Eureka控制檯查看,地址:http://127.0.0.1:8761
常見問題彙總
問題1:Eureka的註冊頁面,發現有一串紅字:
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進入了自我保護機制,默認情況下,如果EurekaServer在一定時間內沒有接收到某個微服務實例的心跳時,EurekaServer將會註銷該實例(默認90s)。但是當網絡發生故障時,微服務與EurekaServer之間無法通信,這樣就會很危險了,因爲微服務本身是很健康的,此時就不應該註銷這個微服務,而Eureka通過自我保護機制來預防這種情況,當網絡健康後,該EurekaServer節點就會自動退出自我保護模式;
這時再次將客戶端微服務啓動,刷新服務註冊中心會發現,自我保護狀態已取消。
配套代碼
主代碼庫:https://github.com/yundianzixun/spring-cloud-study
Eureka Service:https://github.com/yundianzixun/spring-cloud-study/tree/master/microservice-discovery-eureka
microservice-provider-user :https://github.com/yundianzixun/spring-cloud-study/tree/master/microservice-provider-user
microservice-consumer-goods:https://github.com/yundianzixun/spring-cloud-study/tree/master/microservice-consumer-goods