服務註冊與發現

本指南將引導您啟動和使用 Netflix Eureka 服務註冊中心。

您將構建什麼

您將設定一個名為 eureka-serverNetflix Eureka 服務註冊中心,然後構建兩個 Web 客戶端,名為 serviceaserviceb,它們都會向 Eureka server 註冊。其中一個 Web 客戶端 serviceb 將使用 org.springframework.cloud.client.discovery.DiscoveryClientSpring Framework 的 Rest Client 呼叫另一個 Web 客戶端 servicea

您需要什麼

  • 約 15 分鐘

  • 一個您喜歡的文字編輯器或 IDE

  • Java 17 或更高版本

如何完成本指南

與大多數 Spring 入門指南一樣,您可以從頭開始並完成每個步驟,或者透過檢視此倉庫中的程式碼直接跳到解決方案。

要在您的本地環境中檢視最終結果,您可以執行以下操作之一

從 Spring Initializr 開始

對於所有 Spring 應用程式,您應該從 Spring Initializr 開始。Initializr 提供了一種快速方式來引入應用程式所需的所有依賴項,併為您完成大部分設定工作。

本指南需要三個應用程式。第一個應用程式(伺服器應用程式)只需要 Eureka Server 依賴。第二個和第三個應用程式(客戶端應用程式)需要 Eureka Discovery Client 和 Spring Web 依賴。

您可以使用以下連結獲取來自 Spring Initializr 的預初始化專案

由於本指南中的服務數量較多,GitHub 倉庫中僅提供瞭解決方案。要從頭開始,請使用上面的連結或如下所述使用 Spring Initializr 生成空白專案。

手動初始化 Eureka Server 專案

  1. 導航到 https://start.spring.io。此服務會引入應用程式所需的所有依賴項,併為您完成大部分設定工作。

  2. 選擇 Gradle 或 Maven 以及您想要使用的語言。本指南假設您選擇了 Maven 和 Java。

  3. 點選 Dependencies 併為伺服器應用程式選擇 Eureka Server

  4. 點選 Generate

  5. 下載生成的 ZIP 檔案,這是一個根據您的選擇配置好的 Web 應用程式存檔。

手動初始化服務 A 和服務 B 專案

  1. 導航到 https://start.spring.io。此服務會引入應用程式所需的所有依賴項,併為您完成大部分設定工作。

  2. 選擇 Gradle 或 Maven 以及您想要使用的語言。本指南假設您選擇了 Maven 和 Java。

  3. 為客戶端應用程式選擇 Eureka Discovery ClientSpring Web

  4. 點選 Generate

  5. 下載生成的 ZIP 檔案,這是一個根據您的選擇配置好的 Web 應用程式存檔。

如果您的 IDE 集成了 Spring Initializr,您可以在 IDE 中完成此過程。

啟動 Eureka 服務註冊中心

您首先需要一個 Eureka Server。您可以使用 Spring Cloud 的 @EnableEurekaServer 啟動一個註冊中心,其他應用程式可以與其通訊。這是一個常規的 Spring Boot 應用程式,只需新增一個註解 (@EnableEurekaServer) 即可啟用服務註冊。以下列表(來自 eureka-server/src/main/java/com/example/eurekaserver/EurekaServerApplication.java)顯示了伺服器應用程式

package com.example.eurekaserver;

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

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {

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

}

在生產環境中,您可能需要註冊中心的多個例項。您可以在此處找到有關配置 Eureka Server 的更多資訊。

預設情況下,註冊中心也會嘗試註冊自己,因此您需要停用此行為。此外,在本地使用時,將此註冊中心放在一個單獨的埠上是一個很好的約定。

eureka-server/src/main/resources/application.yml 中新增一些屬性來處理這些要求,如下所示

spring:
  application:
    name: eureka-server
server:
  port: 8761
eureka:
  client:
    register-with-eureka: false
    fetch-registry: false
logging:
  level:
    com.netflix.eureka: OFF
    com.netflix.discovery: OFF

您現在可以透過執行 ./mvnw spring-boot:run 啟動 Eureka server。

與註冊中心通訊

啟動服務註冊中心後,您可以啟動與註冊中心互動的客戶端。我們的客戶端應用程式 ServiceA 和 ServiceB 會自動註冊到 Eureka server,因為我們在 classpath 中包含了 spring-cloud-starter-netflix-eureka-client。為避免埠衝突,請在 ServiceA 和 ServiceB 中設定 server.port 引數

服務 A

spring:
  application:
    name: servicea
server:
  port: 8081

服務 B

spring:
  application:
    name: serviceb
server:
  port: 8082

此時,您應該能夠執行所有這三個應用程式。您可以使用 IDE 或從每個應用程式資料夾中執行 ./mvnw spring-boot:run 命令。

應用程式執行後,您可以檢視 Eureka dashboard

eureka server dashboard

服務 A 端點

servicea 專案中建立一個名為 com/example/servicea/controller/ServiceARestController.java 的新類,以暴露一個可用於測試應用程式的端點。

package com.example.servicea.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ServiceARestController {

	@GetMapping("/helloWorld")
	public String helloWorld() {
		return "Hello world from Service A!";
	}

}

服務 B 端點

serviceb 專案中建立一個名為 com/example/serviceb/controller/ServiceBRestController.java 的新類,以暴露一個呼叫 servicea 的端點。

package com.example.serviceb.controller;

import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestClient;

@RestController
public class ServiceBRestController {

	private final DiscoveryClient discoveryClient;
	private final RestClient restClient;

	public ServiceBRestController(DiscoveryClient discoveryClient, RestClient.Builder restClientBuilder) {
		this.discoveryClient = discoveryClient;
		restClient = restClientBuilder.build();
	}

	@GetMapping("helloEureka")
	public String helloWorld() {
		ServiceInstance serviceInstance = discoveryClient.getInstances("servicea").get(0);
		String serviceAResponse = restClient.get()
				.uri(serviceInstance.getUri() + "/helloWorld")
				.retrieve()
				.body(String.class);
		return serviceAResponse;
	}
}

此類別使用 DiscoveryClient 僅根據應用程式名稱查詢 serviceaserviceId。本指南中只有一個 servicea 例項,因此我們只檢視第一個例項。這可以在以下行中看到

ServiceInstance serviceInstance = discoveryClient.getInstances("servicea").get(0);

一旦您獲得了指向 servicea 位置的 ServiceInstance,您現在就可以使用 Spring Framework 的 Rest Client 中的資訊了。

... = restClient.get().uri(serviceInstance.getUri() + "/helloWorld")...

您可以透過執行以下命令測試所有三個應用程式

curl https://:8082/helloEureka

您應該會看到以下結果

Hello world from Service A!

測試應用程式

本指南介紹了以下步驟(您可以透過實現本指南中所示的程式碼或使用解決方案倉庫中的程式碼來完成)

  • eureka-server 資料夾中執行命令 ./mvnw spring-boot:run 啟動 eureka-server

  • servicea 資料夾中執行命令 ./mvnw spring-boot:run 啟動 servicea

  • serviceb 資料夾中執行命令 ./mvnw spring-boot:run 啟動 serviceb

  • 透過訪問 https://:8761/ 上的 Eureka Dashboard,觀察到 serviceaserviceb 已註冊

  • 執行命令 curl https://:8082/helloEureka 測試所有三個應用程式是否正常工作

  • 觀察輸出,應為 Hello world from Service A!

serviceaserviceb 註冊自身並從註冊中心重新整理例項需要一點時間。如果 curl 命令最初失敗,請稍等一分鐘再試。

總結

恭喜!您已成功使用 Spring 啟動了一個 Netflix Eureka 服務註冊中心並在客戶端應用程式中使用了該註冊中心。

另請參閱

以下指南可能也有幫助

想編寫新的指南或為現有指南做出貢獻?請檢視我們的貢獻指南

所有指南的程式碼均採用 ASLv2 許可釋出,文字內容採用 署名-禁止演繹創意共享許可協議

獲取程式碼