公众号「架构成长指南」,专注于生产实践、云原生、分布式系统、大数据技术分享。
在之前的几个教程中,我们学了:
使用 RestTemplate 的 Spring Boot 微服务通信示例
使用 WebClient 的 Spring Boot 微服务通信示例
使用 Spring Cloud Open Feign 的 Spring Boot 微服务通信示例
在本教程中,我们将学习如何在Spring boot微服务项目中使用Spring Cloud Eureka进行服务注册与消费
服务注册和发现概述
在微服务项目中,我们一般会对一个项目,以业务的维度拆分至多个服务,比如用户服务、账务服务、订单服务、仓储服务等,这些服务在生产环境部署,
至少是2个服务实例,如果业务量大几十个都是有可能的。
试想这样一种场景

订单服务实例部署了4个,仓库服务部署了5个,仓库服务要调用订单服务,如果没有注册中心,他会怎么做,那只有把对应的ip和端口写死在代码中,如果新增了一个订单服务怎么办?或者下线了订单服务怎么办?
另外,在云环境中,服务实例随时都有可能启动和关闭,随之IP也会发生变化,没法把IP写死在代码中。
基于以上问题就有了服务注册中心Eureka

Eureka能实现服务自动的注册和发现,在每次服务调用的时候根据服务名称会获取到目标服务的IP和端口,在进行调用。
如果服务下线或者上线,对应的服务的地址信息也会进行更新,这样就保证了,随时可以调用到有效的服务。
同时为了提高性能,这个服务地址信息会在每个服务本地缓存一份地址信息表,定时更新,这样每次请求服务时,不用每次去Eureka查询来降低服务调用耗时。
在本教程中,我们将学习如何使用SpringCloud Eureka进行服务注册和发现,并通过OpenFeign进行服务的调用。
我们将做什么
我们部署一个Eureka Server,并将我们的微服务(部门服务和用户服务)作为 Eureka 客户端,注册到Eureka Server,同时使用用户服务调用根据部门服务的Service ID 来调用部门服务相关接口。

创建Eureka Server
1. 在 IntelliJ IDEA 中创建并设置 Spring boot 项目
让我们使用 springinitializr创建一个 Spring boot 项目。
请参阅下面的屏幕截图,在使用 springinitializr创建 Spring Boot 应用程序时输入详细信息 :

单击生成按钮以 zip 文件形式下载 Spring boot 项目。解压zip文件并在IntelliJ IDEA中导入Spring boot项目。
这是 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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-parent</artifactId>
- <version>2.7.17</version>
- <relativePath/>
- </parent>
- <groupId>io.wz</groupId>
- <artifactId>eureka-server</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- <name>eureka-server</name>
- <description>eureka-server</description>
- <properties>
- <java.version>1.8</java.version>
- <spring-cloud.version>2021.0.8</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>
- <configuration>
- <image>
- <builder>paketobuildpacks/builder-jammy-base:latest</builder>
- </image>
- </configuration>
- </plugin>
- </plugins>
- </build>
- </project>
复制代码 2.添加@EnableEurekaServer注解
我们需要添加@EnableEurekaServer注解,使我们应用程序成为服务注册中心。- package io.wz.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);
- }
- }
复制代码 3. 禁用Eureka Server作为Eureka Client
默认情况下,每个Eureka Server 也是一个Eureka客户端。由于我们只想让他做好服务注册中心,不想让他做客户端,因此我们将通过在application.properties文件中配置以下属性来禁用此客户端行为。- spring.application.name=Eureka Server
- server.port=8761
- eureka.client.register-with-eureka=false
- eureka.client.fetch-registry=false
复制代码 4.启动Eureka服务器
Eureka Server 提供了 UI,我们可以在其中看到有关注册服务的所有详细信息。
现在运行EurekaServerApplication并访问 http://localhost:8761,会显示以下界面

将Department-Service注册至Eureka Server
请参阅本教程创建 部门服务 和 用户服务 微服务: 使用 Spring Cloud Open Feign 的 Spring Boot 微服务通信示例
让我们将这个部门服务 作为 Eureka 客户端并向 Eureka 服务器注册。
将 Eureka client pom添加到部门服务中:- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
- </dependency>
复制代码 另外,添加 Spring Cloud 依赖项:- <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>
复制代码 添加版本属性:- <properties>
- <java.version>1.8</java.version>
- <spring-cloud.version>2021.0.4</spring-cloud.version>
- </properties>
复制代码 在application.properties中配置eureka.client.service-url.defaultZone 属性 即可自动注册到 Eureka Server。- spring.application.name=DEPARTMENT-SERVICE
- eureka.instance.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
复制代码 运行部门服务Eureka客户端
完成此配置后,启动Department-service并访问 http://localhost:8761。
看到部门服务已使用 SERVICE ID 注册为 DEPARTMENT-SERVICE,注意到状态为 UP(1),这意味着服务已启动并正在运行,并且部门服务的一个实例正在运行。

将User-Service微服务注册为Eureka客户端
添加以下依赖- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
- </dependency>
复制代码 在application.properties中配置eureka.client.service-url.defaultZone 属性 即可自动注册到 Eureka Server。- spring.application.name=USER-SERVICE
- eureka.instance.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
复制代码 当服务注册到 Eureka Server 时,它会在一定的时间间隔内不断发送心跳。如果 Eureka 服务器没有收到来自任何服务实例的心跳,它将假定该服务实例已关闭并将其从池中取出
修改user-service的ApiClient
在上一节中中,我们使用APIClient完成了进行服务调用,但是是写了部门服务的url- @FeignClient(value = "DEPARTMENT-SERVICE", url = "http://localhost:8080")
复制代码 这次我们修改如下,去除url属性- @FeignClient(value = "DEPARTMENT-SERVICE")
复制代码 完整api如下- package io.wz.userservice.service;
- import io.wz.userservice.dto.DepartmentDto;
- import org.springframework.cloud.openfeign.FeignClient;
- import org.springframework.web.bind.annotation.GetMapping;
- import org.springframework.web.bind.annotation.PathVariable;
- @FeignClient(value = "DEPARTMENT-SERVICE")
- public interface APIClient {
- @GetMapping(value = "/api/departments/{id}")
- DepartmentDto getDepartmentById(@PathVariable("id") String departmentId);
- }
复制代码 运行用户服务Eureka客户端
以上配置后,启动 user-service 并访问http://localhost:8761。看到user-service已使用 SERVICE ID 注册为USER-SERVICE。
您还可以注意到状态为 UP(1),这意味着服务已启动并正在运行,并且用户服务的一个实例正在运行。

测试
增加测试日志
在部门服务的DepartmentServiceImpl的getDepartmentById方法增加调试日志,如果调用到此接口,会打印getDepartment By Id- @Override
- public Department getDepartmentById(Long departmentId) {
- log.info("getDepartment By Id:{} ",departmentId);
- return departmentRepository.findById(departmentId).get();
- }
复制代码 启动2个Department-Service
1. 启动一个8082的部门服务
在idea中复制DepartmentServiceApplication配置,同时在启动参数指定应用端口 -Dserver.port=8082

2. 启动默认的部门服务,端口为8080

以上2个部门服务启动完成,会在eureka看到2个部门服务

点击获取用户 REST API进行测试
多点击几次,会看到2个部门服务控制台都会打印,getDepartment By Id:1,这里使用的是Spring Cloud LoadBalancer提供的轮训算法


结论
在本教程中,我们学习了如何在 Spring boot 微服务项目中使用Eureka来进行服务的注册与发现,同时基于Feign进行服务的调用,但是这里还有遗留问题,如
- 启动服务以后需要多久才会被消费方查询到地址?
- 如果要做服务更新,如何让消费无感知,感受不到服务再重启?
- 如何让调用方知道调用的是提供方多个实例中具体哪一个服务实例?
以上问题后续文章解答,请关注此公众号。
源码下载:
github
gitee
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |