服务注册与发现

本指南将引导您完成启动和使用 Netflix Eureka 服务注册表的过程。

您将构建什么

您将设置一个名为 eureka-serverNetflix Eureka 服务注册表,然后构建两个名为 serviceaserviceb 的 Web 客户端,它们都向 Eureka 服务器注册。其中一个 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. 单击依赖项并为服务器应用程序选择Eureka Server

  4. 单击生成

  5. 下载生成的 ZIP 文件,它是根据您的选择配置的 Web 应用程序的存档。

手动初始化服务 A 和服务 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 Client 中的信息。

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

您可以通过运行以下命令来测试所有三个应用程序

curl https://127.0.0.1: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://127.0.0.1:8761/ 上的 Eureka 仪表板,观察 serviceaserviceb 是否已注册

  • 运行 curl https://127.0.0.1:8082/helloEureka 命令以测试所有三个应用程序是否正常工作

  • 观察输出,Hello world from Service A!

serviceaserviceb 注册自身并从注册表刷新实例时会稍有延迟。如果 curl 命令最初失败,请等待一分钟然后重试。

总结

恭喜!您刚刚使用 Spring 启动了一个 Netflix Eureka 服务注册表,并在客户端应用程序中使用了该注册表。

另请参阅

以下指南可能也有帮助

想要编写新的指南或为现有指南做出贡献?请查看我们的 贡献指南

所有指南均以 ASLv2 许可证发布代码,并以 署名-非衍生作品创作共用许可证 发布文本。

获取代码