1. 程式人生 > >SpringCloud進擊 | 一淺出:服務註冊與發現(Eureka)【Finchley版本】

SpringCloud進擊 | 一淺出:服務註冊與發現(Eureka)【Finchley版本】


1.前言

Spring Cloud 已經幫我們實現了服務註冊中心,我們只需要很簡單的幾個步驟就可以完成。關於理論知識,我想大家都已經有不同程度上的瞭解和認識,這裡,我們最後再進行總結。本系列 Spring Cloud 介紹基於 Spring Boot 2.0.5 版本和 Spring Cloud Finchley.SR1 版本。

Finchley 版與 Spring Boot 2.0.x 相容,不支援 Spring Boot 1.5.x. 

Spring Cloud 為避免與子專案的釋出號混淆,所以沒有采用版本號的方式,而是通過命名的方式。這些版本名稱的命名方式採用了倫敦地鐵站的名稱,同時根據字母表的順序來對應版本時間順序,比如:最早的Release版本:Angel,第二個Release版本:Brixton,然後是Camden、Dalston、Edgware,目前最新的是Finchley版本。

 

2.準備

我們需要:

  • JDK 1.8或以上
  • Maven 3.0或以上
  • IntelliJ IDEA

另,Spring Cloud 是基於 Spring Boot 的,所以需要我們對 Spring Boot 有一定的瞭解。如果有需要,可以先去連結過一下:
SpringBoot進擊 | 一淺出:Spring Boot簡單快速上手書
SpringBoot進擊 | 二淺出:Spring Boot配置詳解

Finchley版本的官方文件: http://cloud.spring.io/spring-cloud-static/Finchley.RELEASE/single/spring-cloud.html

 

3.進擊

Eureka 這個詞來源於古希臘語,意為 “我找到了!我發現了!”,據傳,阿基米德在洗澡時發現浮力原理,高興得來不及穿上褲子,跑到街上大喊:“Eureka(我找到了)!”。

實踐出真知。

新建一個Maven工程

為了與後面的演練行成連貫性、系統性,這裡我們需要先建立一個Maven主專案。主專案的 pom.xml 檔案作用於版本控制、依賴管理,其它子模組都繼承於該父 pom.xml。

a) File  >>  New  >>  Project  >>  Maven:Project SDK:1.8  >>  [Next] 
b)

填寫Group、ArtifactId等專案資訊  >>  [Next] 
c) 專案名稱、路徑設定  >>  [Finish] 

 

3.1. 服務註冊

3.1.1 建立服務註冊中心(Eureka Server)

3.1.1.1 專案名稱右鍵  >>  Model  >>  選擇 Spring Initializr  >>  Module SDK:1.8;choose Initializr Service URL:Default  >>  [Next] 
3.1.1.2 填寫Group、Artifact等專案資訊  >>  [Next] 


3.1.1.3 Dependencies:專案依賴選擇,選擇 Cloud Discovery,並鉤上 Eureka Server; Spring Boot 版本選擇,這裡我們使用 2.0.5 版本  >>  [Next] 
3.1.1.4 模組名稱、路徑設定  >>  [Finish] 

如此,一個畫風乾淨的 Spring Cloud Eureka Server (Eureka服務註冊中心)就映入眼簾。

因為,它是我們這個專案的一個子模組,它繼承了父pom檔案(parent標籤),並引入了 spring-cloud-starter-netflix-eureka-server 核心依賴,Eureka服務註冊中心的 pom.xml 全配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.wei</groupId>
    <artifactId>wei-eureka-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>wei-eureka-server</name>
    <description>服務註冊中心(Eureka Server)</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.SR1</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</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>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

3.1.2 配置服務註冊中心

在預設設定下,服務註冊中心會將自己作為客戶端來嘗試註冊它自己,所以我們需要禁用它的客戶端註冊行為(預設情況下 Erureka Server 也是一個 Eureka Client,必須要指定一個 Server)。這隻需要在 application.yml (如果創建出來的是properties檔案,可以直接rename成yml)配置檔案中配置以下資訊:

server:
  port: 8090                       # 服務註冊中心埠號配置
eureka:
  instance:
    hostname: localhost            # 服務註冊中心例項的主機名
  client:
    register-with-eureka: false    # 表示是否註冊自身到eureka伺服器,因為當前這個應用就是eureka伺服器,沒必要註冊自身
    fetch-registry: false          # 表示是否從eureka伺服器獲取註冊資訊,同上,這裡不需要
    service-url:                   # defaultZone是指定eureka伺服器的地址,無論是註冊還是發現服務都需要這個地址
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
  server:
    enable-self-preservation: false    # 簡單粗暴把自我保護模式關閉
  • eureka.client.register-with-eureka:表示是否將自己註冊到 Eureka Server,預設為 true
  • eureka.client.fetch-registry:表示是否從 Eureka Server 獲取註冊資訊,預設為 true
  • eureka.client.service-url.defaultZone:是指定 Eureka Server 的地址,無論是註冊還是發現服務都需要這個地址

3.1.3 啟動服務註冊中心

要啟動一個服務註冊中心,只需要在我們剛剛新建的 Eureka Server 模組的啟動類上新增 @EnableEurekaServer 註解即可。

package com.wei;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

/**
 * 註解@EnableEurekaServer,開啟Eureka服務註冊中心功能
 */
@SpringBootApplication
@EnableEurekaServer
public class WeiEurekaServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(WeiEurekaServerApplication.class, args);
    }
}

然後,Run 該啟動類。
如此,一個 Spring Eureka Server 服務註冊中心就被我們建好了。

3.1.4 解讀服務註冊中心

Spring Eureka 服務註冊中心提供了可視介面(Eureka資訊面板)。
我們可以去剛剛配置的URL地址看一下:http://localhost:8090/


當前因為還沒有服務被註冊,所以沒服務可以被發現。

各項備註一下:

System Status  

Environment 指定環境,預設為test, 實際使用過程中,可以不用更改
Data center 資料中心
Current time 當前系統時間
Uptime 已執行時長
Lease expiration enabled 是否啟用租約過期, 自我保護機制關閉時,該值預設是true, 自我保護機制開啟之後為false
Renews threshold server 期望在每分鐘中收到的心跳次數
Renews (last min) 上一分鐘內收到的心跳次數

DS Replicas  

Instances currently registered with Eureka 當前註冊到服務註冊中心內的服務
No instances available 沒有服務被發現

General Info  

total-avail-memory

總共可用的記憶體

environment 環境名稱,預設test
num-of-cpus CPU個數
current-memory-usage 當前已經使用記憶體的百分比
server-uptime 服務線上時間
registered-replicas 相鄰叢集複製節點
unavailable-replicas 不可用的叢集複製節點
available-replicas 可用的相鄰叢集複製節點

Instance Info  

ipAddr 例項IP地址
status 例項狀態

 

Eureka資訊面板的紅字提醒

Spring Eureka 服務註冊中心在三種情況下會出現紅色加粗的字型提示:

1)自我保護機制開啟時(enable-self-preservation: true):
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.

2)自我保護機制關閉時(enable-self-preservation: false):
RENEWALS ARE LESSER THAN THE THRESHOLD. THE SELF PRESERVATION MODE IS TURNED OFF.THIS MAY NOT PROTECT INSTANCE EXPIRY IN CASE OF NETWORK/OTHER PROBLEMS.

3)自我保護機制關閉了,但是一分鐘內的續約數沒有達到85%,可能發生了網路分割槽,會有如下提示
THE SELF PRESERVATION MODE IS TURNED OFF.THIS MAY NOT PROTECT INSTANCE EXPIRY IN CASE OF NETWORK/OTHER PROBLEMS.

 

3.2. 服務發現

3.2.1 建立一個服務提供者(Eureka Client)

服務提供者,也就是 Service Provider,做為一個 Eureka Client,向 Eureka Server 做服務註冊、續約和下線等操作,註冊的主要資料包括服務名、機器IP、埠號、域名等等。

建立步驟與上面的 Eureka Server 建立過程類似,但在Dependencies選擇依賴時,
a) 選擇左側的 Cloud Discovery 後,這裡需要鉤上 Eureka Discovery 項
b) 選擇左側的 Web 後,這裡需要鉤上 Web 項

建立完後的 pom.xml 如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.wei</groupId>
    <artifactId>wei-service-provider</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>wei-service-provider</name>
    <description>服務提供者(Eureka Client)</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.SR1</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <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-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>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
    
</project>

3.2.2 配置服務提供者

修改配置檔案

server:
  port: 8010
spring:
  application:
    name: wei-service-provider    # 指定進行服務註冊時該服務的名稱,服務與服務之間相互呼叫一般都是根據這個name
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8090/eureka/    # 指定進行服務註冊地址

建立服務提供者的服務介面

package com.wei.controller.demo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DemoServiceController {

    @Value("${spring.application.name}")
    private String serviceName;

    @Value("${server.port}")
    private String port;

    @RequestMapping(value = "/demo/info")
    public String getDemoInfo(@RequestParam String name) {
        String result = "Hi," + name + ",我是服務,我被呼叫了,服務名為:" + serviceName + ",埠為:" + port;
        System.out.println(result);
        return result;
    }
}

3.2.3 啟動服務提供者

要啟動一個服務提供者,只需要在我們剛剛新建的 Eureka Clinet 模組的啟動類上新增 @EnableEurekaClient 註解即可。

package com.wei;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

/**
 * 註解@EnableEurekaClient,表明自己是一個Eureka Client
 */
@SpringBootApplication
@EnableEurekaClient
public class WeiServiceProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(WeiServiceProviderApplication.class, args);
    }
}

然後,Run 該啟動類。
如此,一個 Spring Eureka Client 服務提供者就被我們建好了。

去驗證一下吧:http://localhost:8090/

如你所想,一個服務已經註冊在服務中心了,服務名為 WEI-SERVICE-PROVIDER,埠號為8010

再來看看介面:http://localhost:8010/demo/info?name=tester
瀏覽器列印:

Hi,tester,我是服務,我被呼叫了,服務名為:wei-service-provider,埠為:8010

 

到此,簡單易用的 Eureka Server 服務註冊中心就建立完成了。當然,還實現了一個 Eureka Client 服務提供者小樣。

官方參考文件:https://springcloud.cc/spring-cloud-config.html


原始碼:https://github.com/itanping/wei-springcloud/tree/master/chapter01-eureka

下一節,請繼續關注:SpringCloud進擊 | 二淺出:服務消費者(Ribbon+REST)【Finchley版本】