一 服務發(fā)現(xiàn)簡介
當我們在嘗試使用微服務架構(gòu)時,我們會將一個大的單應用拆解成多個獨立自治的小服務,如果在沒有服務發(fā)現(xiàn)的機制下,我們想要在服務之間進行通信,我們只能使用 hard code 的方式,將需要通信的服務的網(wǎng)絡信息寫在服務中。這樣會導致一系列的問題:
- 使用場景有限:如果服務提供者的網(wǎng)絡地址發(fā)生了變化,將會影響服務消費者。
- 無法動態(tài)收縮:在生產(chǎn)環(huán)境中,每個服務一般都會部署多個實例,從而實現(xiàn)容災和負載均衡,硬編碼則無法適應這種需求。
那么要解決這些問題,服務的消費者就需要有一個強大的服務發(fā)現(xiàn)機制,服務消費者使用這個機制獲取服務提供者的網(wǎng)絡信息。即使服務提供者的信息發(fā)生變化,服務消費者也無須修改配置文件。服務發(fā)現(xiàn)組件便提供了這種能力,在微服務架構(gòu)中,服務發(fā)現(xiàn)組件是一個非常重要的組件。

服務發(fā)現(xiàn)架構(gòu)圖
- 在各個服務在啟動時,將自己的網(wǎng)絡地址等信息注冊到服務發(fā)現(xiàn)組件中,服務發(fā)現(xiàn)組件會存儲這些信息。
- 服務消費者可從服務發(fā)現(xiàn)組件中查詢提供者到網(wǎng)絡地址,并使用該地址調(diào)用服務提供者的接口。
- 各個服務與服務發(fā)現(xiàn)組件使用一定機制(例如心跳機制)通信。服務發(fā)現(xiàn)組件如果長時間無法與某微服務實例通信,就會注銷該實例。
- 微服務網(wǎng)絡地址發(fā)生變更時,會重新注冊到微服務發(fā)現(xiàn)組件。
二 Eureka 簡介
Eureka 是Netflix 開源到服務發(fā)現(xiàn)組件,本身是一個基于 REST 到服務,它包含 Server 和 Client 兩部分。 Spring Cloud 將它集成在子項目 Spring Cloud Netflix 中來實現(xiàn)微服務到注冊與發(fā)現(xiàn)。
三 Eureka 原理

Eureka 架構(gòu)圖
其中:
- Application Service 相當于服務提供者
- Application Client 相當于服務消費者
- Make Remote Call 相當于調(diào)用 RESTful API 的行為
Eureka 包含兩個組件:Eureka Server 和 Eureka Client
- Eureka Server 提供服務發(fā)現(xiàn)的能力,各個微服務啟動時,會向 Eureka Server 注冊自己的信息,Eureka Server 會存儲這些信息
- Eureka Client 是一個 Java 客戶端,用于簡化與 Eureka Server 的交互
- 微服務啟動后會周期性(默認30秒)的向 Eureka Server 發(fā)送心跳以續(xù)約自己的“租期“
- 如果 Eureka Server 在一定時間內(nèi)沒有接收到某個服務實例到心跳,那么會注銷該實例
- 默認情況下,Eureka Server 同時也是 Eureka Client,多個 Eureka Server 實例之間是通過復制的方式來實現(xiàn)服務注冊表中數(shù)據(jù)的同步
- Eureka Client 會緩存注冊表中的信息。無須微服務每次請求都查詢 Eureka Server
四 編寫 Eureka Server
- 添加 eureka 依賴
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
- 在啟動類上添加
@EnableEurekaServer注解,聲明這是一個 Eureka Server - 在配置文件
application.yml中添加
server:
port: 8761 # 指定該Eureka實例的端口
eureka:
client:
registerWithEureka: false # 表示是否將自己注冊到 Eureka Server ,默認為 true,由于當前應用就是 Eureka Server,所以設置為 false
fetchRegistry: false # 表示是否從 Eureka Server 中獲取注冊信息,默認為 true,因為這是一個單節(jié)點到 Eureka Server,不需要同步其他到節(jié)點
serviceUrl:
defaultZone: http://localhost:8761/eureka/ #設置與 Eureka Serve 交互到地址,查詢和注冊服務都需要依賴這個地址。默認是 http://localhost:8761/eureka/;多個地址可用逗號分隔
- 訪問 http://localhost:8761
http://localhost:8761
五 將微服務注冊到 Eureka Server 上
- 在微服務應用中添加依賴
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
- 在配置文件中添加
spring:
application:
name: microservice-provider-user # 用于制動注冊到 Eureka Server 上到應用名稱
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true # 將自己到 IP 注冊到 Eureka Server 上,默認為 false,則表示注冊微服務所在操作系統(tǒng)到 hostname 到 Eureka Server 上。
- 啟動類上添加
@EnableDiscoveryCilent注解,聲明這個是一個 Eureka Client。 - 啟動 服務發(fā)現(xiàn)組件APP 和 微服務客戶端,訪問 http://localhost:8761

http://localhost:8761
六 高可用
Eureka Server 可以通過運行多個實例并相互這次的方式實現(xiàn)高可用部署,Eureka Server 會彼此增量的同步信息,從而確保所有節(jié)點數(shù)據(jù)一致。
- 在 hosts 中配置以下信息
127.0.0.1 peer1 peer2
- 將
application.yml配置中添加
spring:
application:
name: microservice-discovery-eureka-ha
---
spring:
profiles: peer1 # 指定profile=peer1
server:
port: 8761
eureka:
instance:
hostname: peer1 # 指定當profile=peer1時,主機名是peer1
client:
serviceUrl:
defaultZone: http://peer2:8762/eureka/ # 將自己注冊到peer2這個Eureka上面去
---
spring:
profiles: peer2
server:
port: 8762
eureka:
instance:
hostname: peer2
client:
serviceUrl:
defaultZone: http://peer1:8761/eureka/
3 將應用注冊到 Eureka Server 上
在 application.yml 中添加
eureka:
client:
serviceUrl:
defaultZone: http://peer1:8761/eureka/
