Spring Cloud 服務註冊與發現、高可用(Eureka)
Spring Cloud 服務註冊與發現、高可用(Eureka)
一、服務發現
1.1 服務發現
在微服務架構中,服務發現元件是很關鍵的一個元件,服務發現元件就是去管理各服務的網路地址等資訊
服務提供者、服務消費者、服務發現元件的關係
- 服務啟動時,會將自己的網路地址等資訊註冊到服務發現元件中,讓服務發現元件去儲存管理這些資訊
- 服務消費者從服務發現元件這裡查詢服務提供者的網路地址資訊,並使用該地址去呼叫服務提供者的介面
- 各服務和服務發現元件通過一定的機制通訊(心跳)
Spring Cloud 支援多種服務發現元件,如 Eureka、Consul 和 Zookeeper 等,這裡主要介紹 Spring Cloud Eureka 的使用
1.2 Eureka 簡介
Eureka 是 Netflix 開源的服務治理模組,本身是一個基於 Rest 的服務。Spring Cloud 中將 Eureka 整合在 Spring Cloud Netflix 專案中,另外 Spring Cloud Netflix 還提供了自配置的Netflix OSS整合。提供的模組包括:服務發現(Eureka),斷路器(Hystrix),智慧路由(Zuul),客戶端負載均衡(Ribbon)等
Eureka 架構圖
Eureka 是包含兩個元件的: Eureka Server
和 Eureka Client
- Eureka Server 提供服務發現的功能,服務啟動後,向 Eureka Server 註冊自己的地址資訊(IP、埠、服務名)
- Eureka Client 是一個客戶端,用於與 Eureka 的互動
- 服務啟動後,與 Eureka Server 通過 心跳 機制通訊,預設週期為 30 秒
- 當 Eureka Server 在一定時間內接收不到某個服務例項的心跳,將會登出該例項,預設時間為 90 秒
- 預設情況下 Eureka Server 同時也是 Eureka Client。多個 Eureka Server 例項通過複製的方式來實現服務註冊
- Eureka Client 有 快取機制,會快取服務登錄檔中的資訊。服務不需要每次請求都查詢 Eureka Server,這樣既降低了 Server 的壓力,同時即便 Eureka Server 的節點都宕機了,也可以使用快取查詢到服務提供者的資訊完成呼叫
二、服務註冊中心 Eureka Server
建立一個 Spring Boot 專案,依賴項 dependencies 新增 Eureka Server
, pom.xml 檔案部分內容如下:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.cindy</groupId>
<artifactId>eureka-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>eureka-server</name>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
要啟動一個服務註冊中心,我們要使用註解 @EnableEurekaServer
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
這個時候如果我們直接啟動,會發現有個連線異常,那是因為預設設定下,服務註冊中心也會把自己當做客戶端來註冊自己,也就是說 eureka server 同時也是一個 eureka client,需要指定一個 server。而通常我們只需要它作為註冊中心,可以使用 eureka.client.registerWithEureka=false
和 eureka.client.fetchRegistry:false
來禁用客戶端註冊行為
spring:
application:
name: eureka-server
server:
port: 8761
eureka:
client:
# 是否將自己註冊到 Eureka Server
registerWithEureka: false
# 是否從 Eureka Server 獲取註冊資訊
fetchRegistry: false
eureka server 有一個UI的主頁,並且
/eureka/*
下有正常 Eureka 功能的HTTP API端點。
啟動工程,訪問 http://localhost:8761可以看到以下頁面,由於還沒有註冊服務,所以沒有被發現的服務
三、註冊服務
上面建立了服務註冊中心
接下來我們來建立服務客戶端,也就是我們要去註冊的服務
還是去建立一個 Spring Boot 工程,要新增的依賴為 Eureka Discovery
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.cindy</groupId>
<artifactId>product</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>product</name>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
同樣的,要使用服務註冊需要主類上添加註解,註解為 @EnableDiscoveryClient
@SpringBootApplication
@EnableDiscoveryClient
public class ProductApplication {
public static void main(String[] args) {
SpringApplication.run(ProductApplication.class, args);
}
}
上面的註解也可使用
@EnableEurekaClient
,而@EnableDiscoveryClient
是spring-cloud-commons
專案的註解,是一個高度的抽象,對各種服務發現元件都提供了支援,如 Zookeeper 和 Consul 也支援
這時需要在客戶端這邊配置服務註冊中心的一些資訊,defaultZone
是與 Eureka Server 互動地址,用於查詢服務和註冊服務 (預設埠是 8761),如果要向多個服務中心註冊用逗號隔開
spring:
application:
name: product
server:
port: 8081
eureka:
client:
serviceUrl:
# 這裡預設是 http://localhost:8761/eureka/
defaultZone: http://localhost:8761/eureka/
如果想要 IP 地址註冊,而不是主機名。可以設定
eureka.instance.preferIpAddress=true
先啟動 Eureka Server,再啟動該工程,我們開啟 Eureka Server 的 UI 介面,可以看到我們的 product 服務已經註冊成功了
四、Eureka 的高可用
儘管 Eureka 的客戶端具有快取機制,即使 Eureka Server 宕機,服務之間也可以通過快取呼叫,但是在 Eureka Server 宕機的時候,一些微服務也可能出現不可用的問題,而這些情況沒有被更新到快取中,就可能會影響到某些微服務的呼叫
生產中通常會部署一個高可用的 Eureka Server 叢集,由上面的 Eureka 架構圖也可以看出可以通過執行多個 Eureka Server 例項並讓他們相互註冊來實現高可用部署。
我們來改一下上面的 eureka-server ,同時啟動兩個例項,來構建雙節點的服務註冊中心
這裡我們要讓 Eureka Server 相互註冊,所以 registerWithEureka
和 fetchRegistry
就不設定未 false 了,而 serviceUrl.defaultZone
則需要填入其他 Eureka Server 的服務地址
spring:
application:
name: eureka-server
---
server:
port: 8761
eureka:
client:
serviceUrl:
defaultZone: http://127.0.0.1:8762/eureka/
---
server:
port: 8762
eureka:
client:
serviceUrl:
defaultZone: http://127.0.0.1:8761/eureka/
這裡我們起兩臺伺服器,埠號分別為 8761 和 8762
啟動之後我們再啟動註冊服務
埠號為 8762 的 server也能獲取埠號為 8761 server 的服務註冊資訊,儘管我們的註冊服務只寫了 http://127.0.0.1:8761/eureka/
, 這裡我們要註冊的服務最好把所有的 Eureka Server 地址都新增上,避免在某些情況下服務重啟會註冊不到
如果要構建多個節點的叢集,其實也是很簡單的,只要它們至少一個邊緣彼此連線,也就是兩兩相互註冊就可以了,同時服務同時