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);
}
}
服务注册与发现
本指南将引导您完成启动和使用 Netflix Eureka 服务注册表的过程。
您将构建什么
您将设置一个名为 eureka-server
的 Netflix Eureka 服务注册表,然后构建两个名为 servicea
和 serviceb
的 Web 客户端,它们都向 Eureka 服务器注册。其中一个 Web 客户端 serviceb
将使用 org.springframework.cloud.client.discovery.DiscoveryClient
和 Spring Framework 的 Rest Client 调用另一个 Web 客户端 servicea
。
您需要什么
-
大约 15 分钟
-
您喜欢的文本编辑器或 IDE
-
Java 17 或更高版本
如何完成本指南
要在本地环境中查看最终结果,您可以执行以下操作之一
-
下载 并解压缩本指南的源代码存储库
-
使用 Git 克隆存储库:
git clone https://github.com/spring-guides/gs-service-registration-and-discovery.git
-
分叉存储库,这使您可以通过提交拉取请求来请求对本指南进行更改
从 Spring Initializr 开始
对于所有 Spring 应用程序,您都应从 Spring Initializr 开始。Initializr 提供了一种快速方法来引入应用程序所需的所有依赖项,并为您完成许多设置工作。
本指南需要三个应用程序。第一个应用程序(服务器应用程序)只需要 Eureka Server 依赖项。第二个和第三个应用程序(客户端应用程序)需要 Eureka Discovery Client 和 Spring Web 依赖项。
您可以使用以下链接从 Spring Initializr 获取预初始化的项目
由于本指南中的服务数量众多,因此 GitHub 存储库中仅提供了解决方案。要从头开始,请使用上面的链接或使用 Spring Initializr 生成空白项目,如下所述。 |
手动初始化 Eureka Server 项目
-
导航到 https://start.spring.io。此服务将引入应用程序所需的所有依赖项,并为您完成大部分设置工作。
-
选择 Gradle 或 Maven 以及您要使用的语言。本指南假设您选择了 Maven 和 Java。
-
单击依赖项并为服务器应用程序选择Eureka Server。
-
单击生成。
-
下载生成的 ZIP 文件,它是根据您的选择配置的 Web 应用程序的存档。
手动初始化服务 A 和服务 B 项目
-
导航到 https://start.spring.io。此服务将引入应用程序所需的所有依赖项,并为您完成大部分设置工作。
-
选择 Gradle 或 Maven 以及您要使用的语言。本指南假设您选择了 Maven 和 Java。
-
为客户端应用程序选择Eureka Discovery Client 和Spring Web。
-
单击生成。
-
下载生成的 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
)显示了服务器应用程序
在生产环境中,您可能希望拥有多个注册表实例。您可以在 此处 找到有关配置 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 仪表板。
服务 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
根据应用程序名称查找 servicea
的 serviceId
。本指南中只有一个 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 仪表板,观察
servicea
和serviceb
是否已注册 -
运行
curl https://127.0.0.1:8082/helloEureka
命令以测试所有三个应用程序是否正常工作 -
观察输出,
Hello world from Service A!
servicea 和 serviceb 注册自身并从注册表刷新实例时会稍有延迟。如果 curl 命令最初失败,请等待一分钟然后重试。 |
总结
恭喜!您刚刚使用 Spring 启动了一个 Netflix Eureka 服务注册表,并在客户端应用程序中使用了该注册表。