1. 程式人生 > >Spring Cloud 服務註冊與發現、高可用(Eureka)

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 ServerEureka 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=falseeureka.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,而 @EnableDiscoveryClientspring-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 相互註冊,所以 registerWithEurekafetchRegistry 就不設定未 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 地址都新增上,避免在某些情況下服務重啟會註冊不到

如果要構建多個節點的叢集,其實也是很簡單的,只要它們至少一個邊緣彼此連線,也就是兩兩相互註冊就可以了,同時服務同時