1. 概述
本文我们来学习 Spring Cloud Netflix 提供的 spring-cloud-netflix-eureka-server 和 spring-cloud-netflix-eureka-server 组件,基于 Spring Cloud 的编程模型,接入 Eureka 作为注册中心,实现服务的注册与发现。
旁白君:下面我们先来科普 Eureka 和注册中心的概念,保持耐心,嘿嘿~
2. Eureka 简介
Eureka 是 Netflix 开源的注册中心组件,分成 Eureka Client 和 Eureka Server 两个角色。整体架构如下图所示:

- Eureka-Server :通过 REST 协议暴露服务,提供应用服务的注册和发现的功能。
- Application Server :应用服务提供者,内嵌 Eureka-Client ,通过它向 Eureka-Server 注册自身服务。
- Application Client :应用服务消费者,内嵌 Eureka-Client ,通过它从 Eureka-Server 获取服务列表。
友情提示:请注意下,Application Server 和 Application Client 强调扮演的角色,实际可以在同一 JVM 进程,即是服务的提供者,又是服务的消费者。
🔥 我们先来看看服务和 Eureka 之间的交互行为:
① Register(注册)
服务提供方使用 Eureka-Client 注册自己到 Eureka-Server 上,添加到注册表,成为服务的一个实例。
友情提示:如果想要深入了解,可阅读《Eureka 源码解析 —— 应用实例注册发现(一)之注册》
② Renew(续租)
服务提供方使用 Eureka-Client 每 30 秒向 Eureka-Server 发起一次心跳,告诉 Eureka-Server 当前服务实例还存活。
友情提示:如果想要深入了解,可阅读《Eureka 源码解析 —— 应用实例注册发现(二)之续租》
如果 Eureka-Server 90 秒没有收到 Eureka-Client 的心跳,会认为它已经下线,将该服务实例从注册表移除。
友情提示:如果想要深入了解,可阅读《Eureka 源码解析 —— 应用实例注册发现(五)之过期》
为什么需要心跳?Eureka 采用 REST 短连接,而非 TCP 长连接,所以需要通过心跳机制来确认是否存活。
③ Get Registry(获取注册信息)
服务消费者使用 Eureka-Client 从 Eureka-Server 获取全量注册表,并缓存在本地内存。之后,服务消费者要远程调用服务提供者时,只需要从本地缓存的注册表查找对应的服务即可。
友情提示:如果想要深入了解,可阅读《Eureka 源码解析 —— 应用实例注册发现(六)之全量获取》
😈 此时,会有一道特别经典的面试题,如果注册中心挂了,是否影响远程调用?
考虑到 Eureka-Server 的注册表是不断变化的,服务消费者每 30 秒使用 Eureka-Client 从 Eureka-Server 获取增量变化的部分,合并更新到本地缓存的注册表。
友情提示:如果想要深入了解,可阅读《Eureka 源码解析 —— 应用实例注册发现(七)之增量获取》
😈 此时,可能会有一道相对较难的面试题,如何实现增量更新?
④ Cancel(下线)
服务提供者准备下线时,使用 Eureka-Client 向 Eureka-Server 发起取消注册请求,从而从注册表中移除,避免后续服务消费者请求当前实例。
一般来说,我们把这种方式称为“正常下线”。与之相对的,就是心跳超时导致的“异常下线”。
友情提示:如果想要深入了解,可阅读《Eureka 源码解析 —— 应用实例注册发现(三)之下线》
🔥 我们先来看看 Eureka-Server 之间的交互行为:
Eureka-Server 在 CAP 定理 中,选择了 AP 来实现:
- 一致性(Consistency):等同于所有节点访问同一份最新的数据副本。
- 可用性(Availability):每次请求都能获取到非错的响应,但是不保证获取的数据为最新数据。
因此,Eureka-Server 集群如下图:

- Eureka-Server 集群不区分主从节点或者 Primary & Secondary 节点,所有节点相同角色( 也就是没有角色 ),完全对等。
- Eureka-Client 可以向任意 Eureka-Client 发起任意读写操作,Eureka-Server 将操作复制到另外的 Eureka-Server 以达到最终一致性。
友情提示:如果想要深入了解,可阅读《Eureka 源码解析 —— Eureka-Server 集群同步》
😈 此时,可能面试官会选择问,Zookeeper 和 Eureka 作为注册中心有什么差别?思考5 分钟,然后可以看看《对于注册中心,ZooKeeper、Eureka 哪个更合适?》
另外,Eureka-Server 还有一个非常重要的概念自我保护机制,胖友可以后续去了解下。不过问了一圈朋友,他们貌似都选择关闭了该特性。
友情提示:如果想要深入了解,可阅读《Eureka 源码解析 —— 应用实例注册发现(四)之自我保护机制》
3. 注册中心原理
本小节,我们再来啰嗦下通用的注册中心原理。
在使用注册中心时,一共有三种角色:服务提供者(Service Provider)、服务消费者(Service Consumer)、注册中心(Registry)。
在一些文章中,服务提供者被称为 Server,服务消费者被称为 Client。胖友们知道即可。
三个角色交互如下图所示:

① Provider:
- 启动时,向 Registry 注册自己为一个服务(Service)的实例(Instance)。
- 同时,定期向 Registry 发送心跳,告诉自己还存活。
- 关闭时,向 Registry 取消注册。
② Consumer:
- 启动时,向 Registry 订阅使用到的服务,并缓存服务的实例列表在内存中。
- 后续,Consumer 向对应服务的 Provider 发起调用时,从内存中的该服务的实例列表选择一个,进行远程调用。
- 关闭时,向 Registry 取消订阅。
③ Registry:
- Provider 超过一定时间未心跳时,从服务的实例列表移除。
- 服务的实例列表发生变化(新增或者移除)时,通知订阅该服务的 Consumer,从而让 Consumer 能够刷新本地缓存。
当然,不同的注册中心可能在实现原理上会略有差异。例如说,Eureka 注册中心,并不提供通知功能,而是 Eureka Client 自己定期轮询,实现本地缓存的更新。
另外,Provider 和 Consumer 是角色上的定义,一个服务同时即可以是 Provider 也可以作为 Consumer。例如说,优惠劵服务可以给订单服务提供接口,同时又调用用户服务提供的接口。
4. 快速入门
示例代码对应仓库:
本小节,我们来搭建一个 Eureka 组件的快速入门示例。步骤如下:
- 首先,使用
spring-cloud-netflix-eureka-server依赖,来搭建一个 Eureka 注册中心。 - 然后,搭建一个服务提供者
demo-provider,注册服务到 Eureka 中。 - 最后,搭建一个服务消费者
demo-consumer,从 Eureka 获取到demo-provider服务的实例列表,选择其中一个示例,进行 HTTP 远程调用。
4.1 搭建 Eureka 注册中心
创建 labx-22-scn-eureka-server-standalone 项目,作为 Eureka 注册中心。最终项目代码如下图所示:

4.1.1 引入依赖
创建 pom.xml 文件,主要引入 Spring Cloud Netflix Eureka Server 相关依赖。代码如下:
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>labx-22</artifactId>
<groupId>cn.iocoder.springboot.labs</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>labx-22-scn-eureka-server-standalone</artifactId>
<properties>
<spring.boot.version>2.2.4.RELEASE</spring.boot.version>
<spring.cloud.version>Hoxton.SR1</spring.cloud.version>
</properties>
<!--
引入 Spring Boot、Spring Cloud、Spring Cloud Alibaba 三者 BOM 文件,进行依赖版本的管理,防止不兼容。
在 https://dwz.cn/mcLIfNKt 文章中,Spring Cloud Alibaba 开发团队推荐了三者的依赖关系
-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<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>
<dependencies>
<!-- 引入 Spring Cloud Netflix Eureka Server 相关依赖,将 Eureka 作为注册中心的服务器,并实现对其的自动配置 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
</project>
通过 spring-cloud-starter-netflix-eureka-server 包,引入 Spring Cloud Netflix Eureka Server 相关依赖,将 Eureka 作为注册中心的服务器,并实现对其的自动配置。
4.1.2 配置文件
创建 application.yaml 配置文件,主要添加 Eureka 相关配置项。配置如下:
server:
port: 8761 # 设置 Eureka-Server 的端口
spring:
application:
name: eureka-server
eureka:
client:
register-with-eureka: false # 不注册到 Eureka-Server,默认为 true
fetch-registry: false # 不从 Eureka-Server 获取注册表,默认为 true
① server.port 配置项,设置启动的 Eureka-Server 的端口。
② eureka.client 配置项,设置 Eureka-Client 配置项,对应 EurekaClientConfigBean 配置类。
Eureka-Server 会启动一个 Eureka-Client 客户端,用于 Eureka-Server 集群之间的请求交互,因为这里我们仅仅搭建 Eureka-Server 单节点,所以设置 register-with-eureka 和 fetch-registry 配置项为 false,无需相互注册。
4.1.3 EurekaServerApplication
创建 EurekaServerApplication 类,Eureka 注册中心的启动类。代码如下:
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class,args);
}
}
在类上添加 @EnableEurekaServer 注解,声明启动 Eureka-Server 服务。
4.1.4 简单测试
我们执行 EurekaServerApplication 来启动注册中心。此时,我们在控制台打印 Eureka 相关的日志如下:
// ... 省略其它日志
2020-05-06 23:36:01.930 INFO 20848 --- [ Thread-17] e.s.EurekaServerInitializerConfiguration : Started Eureka Server
使用浏览器,访问 http://127.0.0.1:8761 地址,可以查看到 Eureka-Server 运维界面。如下图所示:

4.2 搭建服务提供者
创建 labx-22-scn-eureka-demo01-provider 项目,作为服务提供者 demo-provider。最终项目代码如下图所示:

4.2.1 引入依赖
创建 pom.xml 文件,主要引入 Spring Cloud Netflix Eureka Client 相关依赖。代码如下:
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>labx-22</artifactId>
<groupId>cn.iocoder.springboot.labs</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>labx-22-scn-eureka-demo01-provider</artifactId>
<properties>
<spring.boot.version>2.2.4.RELEASE</spring.boot.version>
<spring.cloud.version>Hoxton.SR1</spring.cloud.version>
</properties>
<!--
引入 Spring Boot、Spring Cloud、Spring Cloud Alibaba 三者 BOM 文件,进行依赖版本的管理,防止不兼容。
在 https://dwz.cn/mcLIfNKt 文章中,Spring Cloud Alibaba 开发团队推荐了三者的依赖关系
-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<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>
<dependencies>
<!-- 引入 SpringMVC 相关依赖,并实现对其的自动配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 引入 Spring Cloud Netflix Eureka Client 相关依赖,将 Eureka 作为注册中心的客户端,并实现对其的自动配置 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
</project>
通过 spring-cloud-starter-netflix-eureka-client 包,引入 Spring Cloud Netflix Eureka Client 相关依赖,将 Eureka 作为注册中心的客户端,并实现对其的自动配置。
4.2.2 配置文件
创建 application.yaml 配置文件,主要添加 Eureka 相关配置项。配置如下:
spring:
application:
name: demo-provider # Spring 应用名
server:
port: 18080 # 服务器端口。默认为 8080
eureka:
client:
register-with-eureka: true # 注册到 Eureka-Server,默认为 true
fetch-registry: true # 从 Eureka-Server 获取注册表,默认为 true
service-url:
defaultZone: http://127.0.0.1:8761/eureka/ # Eureka-Server 地址
① 设置 eureka.client.register-with-eureka 为 true,注册当前服务到 Eureka-Server 注册中心中。
② 设置 eureka.client.fetch-registry 为 true,从 Eureka-Server 注册中心拉取注册表。实际上,这里可以设置 false,因为在实例中仅仅扮演服务提供者的角色。
③ eureka.client.service-url 配置项,设置连接的 Eureka-Server 地址。Eureka 是有多 Zone 区域的概念,不过一般用不到,因此这里我们配置 defaultZone 默认区域为 Eureka-Server 地址 http://127.0.0.1:8761/eureka/ 即可,即我们在「4.1 搭建 Eureka 注册中心」小节搭建的 Eureka-Server 的地址。
4.2.3 DemoProviderApplication
创建 DemoProviderApplication 类,创建应用启动类,并提供 HTTP 接口。代码如下:
@SpringBootApplication
@EnableDiscoveryClient
public class DemoProviderApplication {
public static void main(String[] args) {
SpringApplication.run(DemoProviderApplication.class, args);
}
@RestController
static class TestController {
@GetMapping("/echo")
public String echo(String name) {
return "provider:" + name;
}
}
}
① @EnableDiscoveryClient 注解,开启 Spring Cloud 的注册发现功能。不过从 Spring Cloud Edgware 版本开始,实际上已经不需要添加 @EnableDiscoveryClient 注解,只需要引入 Spring Cloud 注册发现组件,就会自动开启注册发现的功能。例如说,我们这里已经引入了 spring-cloud-starter-alibaba-nacos-discovery 依赖,就不用再添加 @EnableDiscoveryClient 注解了。
拓展小知识:在 Spring Cloud Common 项目中,定义了 DiscoveryClient 接口,作为通用的发现客户端,提供读取服务和读取服务列表的 API 方法。而想要集成到 Spring Cloud 体系的注册中心的组件,需要提供对应的 DiscoveryClient 实现类。
例如说,Spring Cloud Alibaba Nacos Discovery 提供了 NacosDiscoveryClient 实现,Spring Cloud Netflix Eureka 提供了 EurekaDiscoveryClient 实现。
如此,所有需要使用到的地方,只需要获取到 DiscoveryClient 客户端,而无需关注具体实现,保证其通用性。
② TestController 类,提供了 /echo 接口,返回 provider:${name} 结果。
4.2.4 简单测试
① 通过 DemoProviderApplication 启动服务提供者,IDEA 控制台输出日志如:
// ... 省略其它日志
2020-05-07 08:59:03.981 INFO 23357 --- [ main] o.s.c.n.e.s.EurekaServiceRegistry : Registering application DEMO-PROVIDER with eureka with status UP
2020-05-07 08:59:03.982 INFO 23357 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_DEMO-PROVIDER/macbook-pro-8:demo-provider:18080: registering service...
2020-05-07 08:59:04.047 INFO 23357 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_DEMO-PROVIDER/macbook-pro-8:demo-provider:18080 - registration status: 204
- 服务
demo-provider注册到 Eureka-Server 上的日志。
② 打开 Eureka 运维界面,可以在服务列表看到服务 demo-provider。如下图:

4.3 搭建服务消费者
创建 labx-22-scn-eureka-demo01-consumer 项目,作为服务提供者 demo-consumer。最终项目代码如下图所示:

整个项目的代码,和服务提供者是基本一致的,毕竟是示例代码 😜
4.3.1 引入依赖
和「3.1.1 引入依赖」一样,只是修改 Maven <artifactId /> 为 labx-01-sca-nacos-discovery-demo01-consumer,见 pom.xml 文件。
4.3.2 配置文件
创建 application.yaml 配置文件,添加相应配置项。配置如下:
spring:
application:
name: demo-consumer # Spring 应用名
server:
port: 28080 # 服务器端口。默认为 8080
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://127.0.0.1:8761/eureka/
和「3.1.2 配置文件」基本一致,主要是将配置项目 spring.application.name 修改为 demo-consumer。
4.3.3 DemoConsumerApplication
创建 DemoConsumerApplication 类,创建应用启动类,并提供一个调用服务提供者的 HTTP 接口。代码如下:
@SpringBootApplication
// @EnableDiscoveryClient
public class DemoConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(DemoConsumerApplication.class, args);
}
@Configuration
public class RestTemplateConfiguration {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
@RestController
static class TestController {
@Autowired
private DiscoveryClient discoveryClient;
@Autowired
private RestTemplate restTemplate;
@Autowired
private LoadBalancerClient loadBalancerClient;
@GetMapping("/hello")
public String hello(String name) {
// <1> 获得服务 `demo-provider` 的一个实例
ServiceInstance instance;
if (true) {
// 获取服务 `demo-provider` 对应的实例列表
List<ServiceInstance> instances = discoveryClient.getInstances("demo-provider");
// 选择第一个
instance = instances.size() > 0 ? instances.get(0) : null;
} else {
instance = loadBalancerClient.choose("demo-provider");
}
// <2> 发起调用
if (instance == null) {
throw new IllegalStateException("获取不到实例");
}
String targetUrl = instance.getUri() + "/echo?name=" + name;
String response = restTemplate.getForObject(targetUrl, String.class);
// 返回结果
return "consumer:" + response;
}
}
}
① @EnableDiscoveryClient 注解,因为已经无需添加,所以我们进行了注释,原因在上面已经解释过。
② RestTemplateConfiguration 配置类,创建 RestTemplate Bean。RestTemplate 是 Spring 提供的 HTTP 调用模板工具类,可以方便我们稍后调用服务提供者的 HTTP API。
③ TestController 提供了 /hello 接口,用于调用服务提供者的 /demo 接口。代码略微有几行,我们来稍微解释下哈。
discoveryClient 属性,DiscoveryClient 对象,服务发现客户端,上文我们已经介绍过。这里我们注入的不是 Eureka 提供的 EurekaDiscoveryClient,保证通用性。未来如果我们不使用 Eureka 作为注册中心,而是使用 Nacos 或则 Zookeeper 时,则无需改动这里的代码。
loadBalancerClient 属性,LoadBalancerClient 对象,负载均衡客户端。稍后我们会使用它,从 Eureka 获取的服务 demo-provider 的实例列表中,选择一个进行 HTTP 调用。
拓展小知识:在 Spring Cloud Common 项目中,定义了LoadBalancerClient 接口,作为通用的负载均衡客户端,提供从指定服务中选择一个实例、对指定服务发起请求等 API 方法。而想要集成到 Spring Cloud 体系的负载均衡的组件,需要提供对应的 LoadBalancerClient 实现类。
例如说,Spring Cloud Netflix Ribbon 提供了 RibbonLoadBalancerClient 实现。
如此,所有需要使用到的地方,只需要获取到 DiscoveryClient 客户端,而无需关注具体实现,保证其通用性。😈 不过貌似 Spring Cloud 体系中,暂时只有 Ribbon 一个负载均衡组件。
当然,LoadBalancerClient 的服务的实例列表,是来自 DiscoveryClient 提供的。
/hello 接口,示例接口,对服务提供者发起一次 HTTP 调用。
<1>处,获得服务demo-provider的一个实例。这里我们提供了两种方式的代码,分别基于 DiscoveryClient 和 LoadBalancerClient。<2>处,通过获取到的服务实例 ServiceInstance 对象,拼接请求的目标 URL,之后使用 RestTemplate 发起 HTTP 调用。
4.3.4 简单测试
① 通过 DemoConsumerApplication 启动服务消费者,IDEA 控制台输出日志如:
// ... 省略其它日志
2020-05-07 09:13:24.639 INFO 23835 --- [ main] o.s.c.n.e.s.EurekaServiceRegistry : Registering application DEMO-CONSUMER with eureka with status UP
2020-05-07 09:13:24.640 INFO 23835 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_DEMO-CONSUMER/macbook-pro-8:demo-consumer:28080: registering service...
2020-05-07 09:13:24.662 INFO 23835 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_DEMO-CONSUMER/macbook-pro-8:demo-consumer:28080 - registration status: 204
- 服务
demo-consumer注册到 Eureka 上的日志。
注意,服务消费者和服务提供是一种角色的概念,本质都是一种服务,都是可以注册自己到注册中心的。
② 打开 Eureka 运维界面,可以在服务列表看到服务 demo-consumer。如下图:

③ 访问服务消费者的 http://127.0.0.1:28080/hello?name=yudaoyuanma 接口,返回结果为 "consumer:provider:yudaoyuanma"。说明,调用远程的服务提供者成功。
④ 关闭服务提供者后,再次访问 http://127.0.0.1:28080/hello?name=yudaoyuanma 接口,返回结果如下图所示:
因为 Eureka-Client 是每 30 秒定时轮询获取增量变化的注册表,从而更新本地的服务实例缓存。因此,这里还是会去请求已关闭的服务提供者。这个一定要注意!!!
友情提示:目前来说,还是比较推荐采用 Nacos 作为注册中心。感兴趣的胖友,可以阅读《芋道 Spring Cloud Alibaba 注册中心 Nacos 入门》文章。
⑤ 等待 30 秒左右后,再次访问 http://127.0.0.1:28080/hello?name=yudaoyuanma 接口,返回结果为报错提示 "获取不到实例",说明我们本地缓存的服务 demo-provider 的实例列表已刷新,没有任何实例。
😈 这里我们并没有演示启动多个服务提供者的测试,胖友可以自己尝试下哟。
5. 高可用 Eureka 集群
示例代码对应仓库:
本小节,我们来搭建多个 Eureka-Server 节点,让它们相互注册,从而形成注册中心高可用集群。
考虑到方便,我们直接在「4. 快速入门」小节的基础上进行改造,搭建本小节的示例。项目复制如下图所示:

5.1 搭建 Eureka 注册中心
从「4.1 搭建 Eureka 注册中心」小节的 labx-22-scn-eureka-server-standalone 项目,复制出 labx-22-scn-eureka-server-cluster 项目。修改点如下图所示:

// application-node01.yaml
server:
port: 18761
spring:
application:
name: eureka-server
eureka:
instance:
hostname: eureka-node01
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://eureka-node02:28761/eureka/
// application-node02.yaml
server:
port: 28761
spring:
application:
name: eureka-server
eureka:
instance:
hostname: eureka-node02
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://eureka-node01:18761/eureka/
① server.port 配置项目,设置 Eureka-Server 启动的端口。
② eureka.instance.hostname 配置,设置注册的主机名为 eureka-node01 和 eureka-node02。
同时修改本地 host 文件,设置这两个主机名映射的 IP 地址。因为我们这里在本机搭建 Eureka-Server,所以设置为 127.0.0.1。
友情提示:如果胖友部署在正式服务器上,需要设置服务器的内网 IP。
127.0.0.1 eureka-node01
127.0.0.1 eureka-node02
③ eureka.client.register-with-eureka 和 eureka.client.fetch-registry 配置项,都设置为 true,因为要进行注册。
同时,将 eureka.client.service-url.defaultZone 配置项,设置为排除自己之外的所有其它 Eureka-Server 节点的地址。
下面,我们来通过 EurekaServerApplication 启动 Eureka-Server 节点,通过 --spring.profiles.active 设置分别为 node01 和 node02,从而读取不同的配置文件。如下图所示:
启动时,看到 IDEA 控制台会有报错的提示,可以忽略。因为互相注册到对方,而对方又未重启,所以会出现注册失败的报错。稍等片刻,我们就会看到它们相互注册成功,如下图所示:

5.2 搭建服务提供者
从「4.2 搭建服务提供者」小节的 labx-22-scn-eureka-demo01-provider 项目,复制出 labx-22-scn-eureka-demo02-provider 项目。修改点如下图所示:

spring:
application:
name: demo-provider # Spring 应用名
server:
port: 18080 # 服务器端口。默认为 8080
eureka:
client:
register-with-eureka: true # 注册到 Eureka-Server,默认为 true
fetch-registry: true # 从 Eureka-Server 获取注册表,默认为 true
service-url:
defaultZone: http://eureka-node01:18761/eureka/, http://eureka-node02:28761/eureka/
设置 eureka.client.service-url.defaultZone 配置项为所有 Eureka-Server 节点的地址。
5.3 搭建服务消费者
从「4.3 搭建服务消费者」小节的 labx-22-scn-eureka-demo01-consumer 项目,复制出 labx-22-scn-eureka-demo02-provider 项目。修改点如下图所示:

spring:
application:
name: demo-consumer # Spring 应用名
server:
port: 28080 # 服务器端口。默认为 8080
eureka:
client:
register-with-eureka: true # 注册到 Eureka-Server,默认为 true
fetch-registry: true # 从 Eureka-Server 获取注册表,默认为 true
service-url:
defaultZone: http://eureka-node01:18761/eureka/, http://eureka-node02:28761/eureka/
5.4 简单测试
① 通过 DemoProviderApplication 启动服务提供者,成功注册到 Eureka-Server 集群。如下图所示:

② 通过 DemoConsumerApplication 启动服务消费者,访问 http://127.0.0.1:28080/hello?name=yudaoyuanma 接口,返回结果为 "consumer:provider:yudaoyuanma",调用成功。
下面,我们来尝试关闭一个 Eureka-Server 节点,会看到其它 Eureka-Server 标记关闭的 Eureka-Server 节点为不可用。如下图所示:

6. 安全认证
示例代码对应仓库:
考虑到安全性,我们可以使用 Spring Security 给 Eureka-Server 增加认证功能。
考虑到方便,我们直接在「4. 快速入门」小节的基础上进行改造,搭建本小节的示例。项目复制如下图所示:

😈 主要步骤是,给 Eureka-Server 增加安全认证,同时在 Eureka-Client 连接 Eureka-Server 需要使用账号进行认证。
6.1 搭建 Eureka 注册中心
从「4.1 搭建 Eureka 注册中心」小节的 labx-22-scn-eureka-server-standalone 项目,复制出 labx-22-scn-eureka-server-security 项目。修改点如下图所示:

6.1.1 引入依赖
在 pom.xml 文件中,额外引入相关依赖。
<!-- 实现对 Spring Security 的自动化配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
6.1.2 配置文件
修改 application.yaml 配置文件,通过 spring.security.user 配置项来添加默认的 Spring Security 认证账号。配置如下:
server:
port: 8761 # 设置 Eureka-Server 的端口
spring:
application:
name: eureka-server
# 使用 Spring Security 创建默认认证账号
security:
user:
name: eureka
password: woshimima
eureka:
client:
register-with-eureka: false # 不注册到 Eureka-Server,默认为 true
fetch-registry: false # 不从 Eureka-Server 获取注册表,默认为 true
6.1.3 WebSecurityConfig
创建 WebSecurityConfig 配置类,设置 Eureka-Server 提供的 /eureka/** 无需传递 CSRF Token,代码如下:
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().ignoringAntMatchers("/eureka/**");
super.configure(http);
}
}
默认配置下,Spring Security 要求每个强求需要携带 CSRF Token 才可以访问,而 Eureka-Client 是不会进行携带的,因此需要针对 /eureka/** 路径进行禁用,不然就要改 Eureka-Client 的源码啦~~~
6.1.4 简单测试
① 我们执行 EurekaServerApplication 来启动注册中心。
② 使用浏览器,访问 http://127.0.0.1:8761 地址,自动重定向到 Spring Security 内置的登陆界面。如下图所示:

使用我们配置的「eureka/woshimima」账号,进行登陆。登陆完成,进入 Eureka 运维界面。如下图所示:

6.2 搭建服务提供者
从「4.2 搭建服务提供者」小节的 labx-22-scn-eureka-demo01-provider 项目,复制出 labx-22-scn-eureka-demo03-provider 项目。修改点如下图所示:

spring:
application:
name: demo-provider # Spring 应用名
server:
port: 18080 # 服务器端口。默认为 8080
eureka:
client:
register-with-eureka: true # 注册到 Eureka-Server,默认为 true
fetch-registry: true # 从 Eureka-Server 获取注册表,默认为 true
service-url:
defaultZone: http://eureka:woshimima@127.0.0.1:8761/eureka/ # Eureka-Server 地址
按照 http://{账号}:{密码}@{Eureka-Server 地址} 的格式,我们设置 eureka.client.service-url.defaultZone 配置项为 http://eureka:woshimima@127.0.0.1:8761/eureka/。
6.3 搭建服务消费者
从「4.2 搭建服务提供者」小节的 labx-22-scn-eureka-demo01-consumer 项目,复制出 labx-22-scn-eureka-demo03-consumer 项目。修改点如下图所示:

spring:
application:
name: demo-consumer # Spring 应用名
server:
port: 28080 # 服务器端口。默认为 8080
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://eureka:woshimima@127.0.0.1:8761/eureka/ # Eureka-Server 地址
按照 http://{账号}:{密码}@{Eureka-Server 地址} 的格式,我们设置 eureka.client.service-url.defaultZone 配置项为 http://eureka:woshimima@127.0.0.1:8761/eureka/。
6.4 简单测试
① 通过 DemoProviderApplication 启动服务提供者,成功注册到 Eureka-Server 注册中心。如下图所示:

② 通过 DemoConsumerApplication 启动服务消费者,访问 http://127.0.0.1:28080/hello?name=yudaoyuanma 接口,返回结果为 "consumer:provider:yudaoyuanma",调用成功。
至此,我们已经完成 Spring Cloud Eureka 的学习。如下是 Eureka 相关的官方文档:



477

被折叠的 条评论
为什么被折叠?



