Spring Cloud 注册中心 Consul 入门

25 篇文章 2 订阅
10 篇文章 3 订阅

1. 概述

《Consul 极简入门》文章中,我们一起完成了 Consul 的学习,并完成了 Consul 服务器的搭建。

本文我们来学习 Spring Cloud Consul 提供的 spring-cloud-consul-discovery 组件,基于 Spring Cloud 的编程模型,接入 Consul 作为注册中心,实现服务的注册与发现

2. 注册中心原理

在开始搭建 Consul Discovery 的示例之前,我们先来简单了解下注册中心的原理。

在使用注册中心时,一共有三种角色:服务提供者(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。例如说,优惠劵服务可以给订单服务提供接口,同时又调用用户服务提供的接口。

3. 快速入门

示例代码对应仓库:

本小节,我们来搭建一个 Consul Discovery 组件的快速入门示例。步骤如下:

  • 首先,搭建一个服务提供者 demo-provider ,注册服务到 ZooKeeper 中。
  • 然后,搭建一个服务消费者 demo-consumer,从 ZooKeeper 获取到 demo-provider 服务的实例列表,选择其中一个示例,进行 HTTP 远程调用。

3.1 搭建服务提供者

创建 labx-27-sc-consul-discovery-demo01-provider 项目,作为服务提供者 demo-provider。最终项目代码如下图所示:

项目

3.1.1 引入依赖

在 pom.xml 文件中,主要引入 Spring Cloud Consul Discovery 相关依赖。代码如下:

<?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-27</artifactId>
        <groupId>cn.iocoder.springboot.labs</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>labx-27-sc-consul-discovery-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 Consul Discovery 相关依赖,将 Consul 作为注册中心,并实现对其的自动配置 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>

        <!-- 引入 Spring Boot Actuator 组件,因为需要通过它提供健康检查的接口给 Consul -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    </dependencies>

</project>

① 引入 spring-cloud-starter-consul-discovery 依赖,将 Consul 作为注册中心,并实现对它的自动配置。

② 引入 spring-boot-starter-actuator 依赖,添加 Spring Boot Actuator 组件,因为需要通过它提供健康检查的接口给 Consul。

3.1.2 配置文件

创建 application.yaml 配置文件,添加 Consul Discovery 配置项。配置如下:

spring:
  application:
    name: demo-provider # Spring 应用名
  cloud:
    # Spring Cloud Consul 通用配置项,对应 ConsulProperties 类
    consul:
      host: 127.0.0.1 # Consul 主机
      port: 8500 # Consul 端口
      # Spring Cloud Consul Discovery 配置项,对应 ConsulDiscoveryProperties 类
      discovery:
        service-name: ${spring.application.name} # 注册到 Consul 的服务名,默认为 `spring.application.name` 配置项
        health-check-path: /actuator/health # 健康检查的接口,默认为 /actuator/health,由 Spring Boot Actuator 提供

server:
  port: 18080 # 服务器端口。默认为 8080

① spring.cloud.consul 配置项,设置 Consul 客户端的配置,对应 ConsulProperties 配置类。

通过 host 和 port 配置项,设置 Consul 服务器的地址。

② spring.cloud.consul.discovery 配置项,设置 ZooKeeper Discovery 配置项,对应 ConsulDiscoveryProperties 配置类。

  • service-name 配置项,设置注册到 Consul 的服务名,默认为 spring.application.name 配置项。
  • health-check-path 配置项,设置 Consul 健康检查的接口,默认为 /actuator/health,由 Spring Boot Actuator 提供。

3.1.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;
        }

    }

}

① @SpringBootApplication 注解,被添加在类上,声明这是一个 Spring Boot 应用。Spring Cloud 是构建在 Spring Boot 之上的,所以需要添加。

② @EnableDiscoveryClient 注解,开启 Spring Cloud 的注册发现功能。不过从 Spring Cloud Edgware 版本开始,实际上已经不需要添加 @EnableDiscoveryClient 注解,只需要引入 Spring Cloud 注册发现组件,就会自动开启注册发现的功能。例如说,我们这里已经引入了 spring-cloud-starter-zookeeper-discovery 依赖,就不用再添加 @EnableDiscoveryClient 注解了。

拓展小知识:在 Spring Cloud Common 项目中,定义了 DiscoveryClient 接口,作为通用的发现客户端,提供读取服务和读取服务列表的 API 方法。而想要集成到 Spring Cloud 体系的注册中心的组件,需要提供对应的 DiscoveryClient 实现类。

例如说,Spring Cloud Alibaba Nacos Discovery 提供了 NacosDiscoveryClient 实现,Spring Cloud Consul Discovery 提供了 ConsulDiscoveryClient 实现。

如此,所有需要使用到的地方,只需要获取到 DiscoveryClient 客户端,而无需关注具体实现,保证其通用性。

③ TestController 类,提供了 /echo 接口,返回 provider:${name} 结果。

3.1.4 简单测试

通过 DemoProviderApplication 启动服务提供者。启动完成后,我们可以在 Consul 运维界面,看到该服务提供者。如下图所示:

我是动图

3.2 搭建服务消费者

创建 labx-27-sc-consul-discovery-demo01-consumer 项目,作为服务提供者 demo-consumer。最终项目代码如下图所示:

项目

整个项目的代码,和服务提供者是基本一致的,毕竟是示例代码 😜

3.2.1 引入依赖

「3.1.1 引入依赖」一样,只是修改 Maven <artifactId /> 为 labx-27-sc-consul-discovery-demo01-consumer,见 pom.xml 文件。

3.2.2 配置文件

创建 application.yaml 配置文件,添加相应配置项。配置如下:

spring:
  application:
    name: demo-consumer # Spring 应用名

  cloud:
    # Spring Cloud Consul 通用配置项,对应 ConsulProperties 类
    consul:
      host: 127.0.0.1 # Consul 主机
      port: 8500 # Consul 端口
      # Spring Cloud Consul Discovery 配置项,对应 ConsulDiscoveryProperties 类
      discovery:
        service-name: ${spring.application.name} # 注册到 Consul 的服务名,默认为 `spring.application.name` 配置项
        health-check-path: /actuator/health # 健康检查的接口,默认为 /actuator/health,由 Spring Boot Actuator 提供

server:
  port: 28080 # 服务器端口。默认为 8080

「3.1.2 配置文件」基本一致,主要是将配置项目 spring.application.name 修改为 demo-consumer

3.2.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 对象,服务发现客户端,上文我们已经介绍过。这里我们注入的不是 Nacos Discovery 提供的 NacosDiscoveryClient,保证通用性。未来如果我们不使用 Nacos 作为注册中心,而是使用 Eureka 或则 ZooKeeper 时,则无需改动这里的代码。

loadBalancerClient 属性,LoadBalancerClient 对象,负载均衡客户端。稍后我们会使用它,从 Nacos 获取的服务 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 调用。

3.2.4 简单测试

① 通过 DemoConsumerApplication 启动服务消费者。启动完成后,我们可以在 Consul 运维界面,看到该服务消费者。如下图所示:

我是静图

注意,服务消费者和服务提供是一种角色的概念,本质都是一种服务,都是可以注册自己到注册中心的。

② 访问服务消费者的 http://127.0.0.1:28080/hello?name=yudaoyuanma 接口,返回结果为 "consumer:provider:yudaoyuanma"。说明,调用远程的服务提供者成功。

③ 关闭服务提供者后,再次访问 http://127.0.0.1:28080/hello?name=yudaoyuanma 接口,返回结果为报错提示 "获取不到实例",说明我们本地缓存的服务 demo-provider 的实例列表已刷新,没有任何实例。

至此,我们已经完成 Spring Cloud Consul 作为注册中心的学习。如下是 Consul Discovery 相关的官方文档:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值