服務註冊與發現

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

您將構建什麼

您將設定一個名為 eureka-serverNetflix Eureka 服務註冊中心,然後構建兩個名為 serviceaserviceb 的 Web 客戶端,它們都註冊到 Eureka 伺服器。其中一個 Web 客戶端 serviceb 將使用 org.springframework.cloud.client.discovery.DiscoveryClientSpring Framework 的 Rest 客戶端 呼叫另一個 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. 單擊生成

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

手動初始化 Service A 和 Service B 專案

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

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

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

  4. 單擊生成

  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 伺服器。

與註冊中心通訊

現在您已經啟動了一個服務註冊中心,您可以啟動與註冊中心互動的客戶端。我們的客戶端應用程式 ServiceA 和 ServiceB 會自動註冊到 Eureka 伺服器,因為我們的類路徑上有 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 儀表板

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 客戶端中使用這些資訊了。

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

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

curl https://:8082/helloEureka

您應該會看到結果

Hello world from Service A!

測試應用程式

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

  • eureka-server 資料夾執行 eureka-server,使用命令 ./mvnw spring-boot:run

  • servicea 資料夾執行 servicea,使用命令 ./mvnw spring-boot:run

  • serviceb 資料夾執行 serviceb,使用命令 ./mvnw spring-boot:run

  • 透過在 https://:8761/ 檢視 Eureka 儀表板來觀察 serviceaserviceb 已註冊

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

  • 觀察輸出:Hello world from Service A!

serviceaserviceb 註冊自己並從註冊中心重新整理例項需要短暫的延遲。如果 curl 命令最初失敗,請等待一分鐘再試一次。

總結

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

另請參閱

以下指南也可能有所幫助

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

所有指南的程式碼均採用 ASLv2 許可,文字內容採用署名-禁止演繹知識共享許可

獲取程式碼