Spring Cloud Netflix 注册中心 Eureka 入门

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 整体架构

  • 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 集群

  • 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 注册中心。最终项目代码如下图所示:

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 运维界面。如下图所示:

Eureka-Server 运维界面

4.2 搭建服务提供者

创建 labx-22-scn-eureka-demo01-provider 项目,作为服务提供者 demo-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。最终项目代码如下图所示:

`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 `node01`
  • IDEA `node02`

启动时,看到 IDEA 控制台会有报错的提示,可以忽略。因为互相注册到对方,而对方又未重启,所以会出现注册失败的报错。稍等片刻,我们就会看到它们相互注册成功,如下图所示:

Eureka-Server 注册中心

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 节点为不可用。如下图所示:

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 运维界面。如下图所示:

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 相关的官方文档:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值