Consul 入门教程 - 基础篇(2024 年)

大纲

Consul 介绍

Consul 的简介

  • Consul 是一个支持多数据中心分布式高可用的服务发现和配置共享的服务软件,由 HashiCorp 公司使用 Go 语言开发,基于 Mozilla Public License 2.0 的协议进行开源。Consul 支持健康检查,并允许 HTTP 、gRPC 和 DNS 协议调用 API 存储键值对。
  • 一致性协议采用 Raft 算法,用来保证服务的高可用。使用 GOSSIP 协议管理成员和广播消息,并且支持 ACL 访问控制。
  • 命令行超级好用的虚拟机管理软件 Vgrant 也是 HashiCorp 公司开发的产品。

Consul 的集群概念

  • Client:表示 Consul 客户端模式,是 Consul 节点的一种模式,所有注册到 Client 节点的服务都会被转发给 Server 节点。Client 本身是无状态的,且不持久化任何数据。Client 会通过 HTTP、DNS、gRPC 将请求转发给局域网内的 Server 集群。
  • Server:表示 Consul 的服务端模式, Server 的功能和 Client 一样,但不同的是 Server 会持久化数据到本地。在局域网内与本地 Client 通讯,通过广域网与其他数据中心通讯。每个数据中心的 Server 数量推荐为 3 个或是 5 个。
  • Server-Leader:Server 的老大,它和其它 Server 不一样的是,它需要将注册信息同步给其它的 Server 节点,同时也要负责各个节点的健康监测。如果 Leader 宕机了,会在所有 Server 的内部使用 Raft 算法来在其中选举一个新的 Leader。
  • Agent:Agent 是 Consul 的核心进程,Agent 负责维护成员关系信息、注册服务、健康检查、响应查询等。Consul 集群的每一个节点(无论是 Server 还是 Client)都必须运行 Agent 进程。

总结

  • Server 节点:负责数据存储、Leader 选举和集群一致性。
  • Client 节点:用于服务注册、健康检查和负载均衡,作为轻量代理。
  • Agent 代理:所有节点的守护进程,管理本地健康检查和服务发现。

Client 模式与 Server 模式

在 Consul 中,Client 模式和 Server 模式是两种不同的运行模式,每种模式在 Consul 集群中承担的角色和职责不同。以下是它们的区别:

  • 角色与职责

    • Server 模式:

      • 核心功能:Consul 服务器节点是集群的核心,负责存储集群状态数据、维护服务目录、处理数据查询和写入请求、选举领导者、以及处理其他控制平面操作。
      • 数据存储:服务器节点持久化存储所有的服务注册信息、健康检查状态、KV 存储数据等。
      • 选举与一致性:多个服务器节点之间通过 Raft 协议来选举领导者(Leader),并且通过复制日志的方式确保数据的一致性和高可用性。
      • 数量要求:集群中应该至少有 3 个服务器节点(生产环境下建议 5 个),以确保故障时仍能维持集群的高可用性。
    • Client 模式:

      • 核心功能:客户端节点负责代理应用程序的请求,将它们转发给服务器节点处理。客户端不会持久化存储集群状态数据。
      • 轻量级:客户端节点不参与选举和数据一致性操作,因此占用的资源较少。它主要用于收集本地服务的健康检查结果,并向服务器节点发送这些数据。
      • 网络代理:客户端节点可以作为网络代理,帮助服务发现和服务请求的转发,从而在不同服务之间提供负载均衡和服务路由。
  • 数据存储

    • Server 模式:服务器节点持久化存储集群的状态数据,例如服务注册信息、健康检查结果、KV 存储等。
    • Client 模式:客户端节点不存储任何持久化数据,只将数据发送给服务器节点。
  • 通信与代理

    • Server 模式:服务器节点可以直接处理来自客户端节点的请求,并负责将请求结果返回给客户端。
    • Client 模式:客户端节点负责接收本地服务的请求,并将这些请求转发给服务器节点处理,然后将结果返回给应用程序。
  • 高可用性

    • Server 模式:为了保证高可用性,集群中应该至少配置 3 个服务器节点(生产环境下建议 5 个),这样即使有一个或两个节点发生故障,集群仍然可以正常工作。
    • Client 模式:客户端节点可以是任意数量,增加客户端节点不会对集群的高可用性产生影响。客户端节点失败不会影响集群整体的运行。
  • 工作负载

    • Server 模式:因为需要参与一致性协议(如 Raft),并处理数据存储、复制等操作,所以服务器节点的负载通常会较高。
    • Client 模式:客户端节点的工作负载较低,因为它们只需处理本地请求的转发和健康检查数据的收集。
  • 部署建议

    • Server 模式:服务器节点通常部署在稳定且高性能的机器上,建议将它们分散在不同的可用区或数据中心,以提高容灾能力。
    • Client 模式:客户端节点可以部署在每个应用服务所在的机器上,以便就近收集健康检查信息并进行服务发现。

总结

  • Server 节点(使用 Server 模式)是 Consul 集群的核心,负责处理集群状态和一致性、参与选举、存储所有数据。
  • Client 节点(使用 Client 模式)则是轻量级的代理,负责转发请求,不存储数据,只用于连接和与服务器节点交互。

Consul 配置中心

使用案例

本节将演示 Consul 作为配置中心的使用案例,由于篇幅有限,只给出核心代码和配置信息。

版本说明

组件名版本
Java17+
Spring Boot3.2.0
Spring Cloud2023.0.0

核心代码

  • 引入依赖
1
2
3
4
5
6
7
8
9
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-config</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
  • 配置属性类
1
2
3
4
5
6
7
8
9
10
11
12
import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

@Getter
@Configuration
public class AppProperties {

@Value("${env.info:}")
private String envInfo;

}

配置文件

配置规则说明

Spring Cloud Consul 在 官方文档 中提到过,要求在 bootstrap.yml 中配置 Consul 配置中心,并遵从一定的配置规则。

创建 YML 配置文件

在项目中创建 bootstrap.yml 配置文件,并添加以下配置信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
spring:
application:
name: cloud-payment-service
cloud:
consul:
host: 127.0.0.1 # Consul 启动地址
port: 8500 # Consul 启动端口
config:
format: YAML # Consul 中 Value 的配置格式为 YAML
prefix: config # Consul 中的配置文件目录,默认为 config
default-context: app # 去该目录下查找缺省配置,默认为 application
profile-separator: '-' # profiles 配置的分隔符,默认为 ','
data-key: data # 如果指定配置格式为 YAML 或者 Properties,则需要该值作为 key,默认为 data

添加配置信息

访问 Consul 的 UI 界面,比如 http://127.0.0.1:8500/,然后手动添加不同环境(比如默认环境、开发环境、测试环境)的配置信息,如下图所示。

默认环境的配置信息
  • 首先创建 config 文件夹,必须以 / 结尾

  • 然后,在 config 文件夹下创建 cloud-payment-service 文件夹(名称必须跟微服务应用的名称一致),必须以 / 结尾

  • 最后,在 cloud-payment-service 文件夹下面创建 data 配置信息,这里的 data 不再是文件夹,而是 key

开发环境的配置信息
  • 首先创建 config 文件夹,必须以 / 结尾

  • 然后,在 config 文件夹下创建 cloud-payment-service-dev 文件夹(名称由微服务应用的名称 + Profiles 组成,比如 dev 表示开发环境),必须以 / 结尾

  • 最后,在 cloud-payment-service-dev 文件夹下面创建 data 配置信息,这里的 data 不再是文件夹,而是 key

测试环境的配置信息
  • 首先创建 config 文件夹,必须以 / 结尾

  • 然后,在 config 文件夹下创建 cloud-payment-service-test 文件夹(名称由微服务应用的名称 + Profiles 组成,比如 test 表示测试环境),必须以 / 结尾

  • 最后,在 cloud-payment-service-test 文件夹下面创建 data 配置信息,这里的 data 不再是文件夹,而是 key

测试代码

  • 添加测试接口
1
2
3
4
5
6
7
8
9
10
11
12
13
@RestController
@RequestMapping("/config")
public class ConfigController {

@Autowired
private AppProperties properties;

@GetMapping("/envInfo")
public String envInfo() {
return properties.getEnvInfo();
}

}
  • application.yml 配置文件
1
2
3
4
5
6
7
server:
port: 8080

spring:
# 激活不同的配置环境
profiles:
active: dev
  • 测试步骤
    • (1) 启动微服务应用,访问 http://127.0.0.1:8080/config/info 测试接口,观察接口的返回结果是不是 Dev Env
    • (2) 将 application.yml 配置文件中的 active: dev 更改为 active: test,然后重启微服务应用。
    • (3) 再次访问 http://127.0.0.1:8080/config/info 测试接口,观察接口的返回结果是不是 Test Env

动态刷新配置信息

Spring Cloud Consul 支持动态刷新配置信息,也就是当用户在 Consul 的 UI 管理界面更改了配置信息,微服务应用可以实时感知到并执行更新操作。当使用动态刷新配置信息时,只需要添加 @RefreshScope 注解即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Configuration;

@Getter
@RefreshScope
@Configuration
public class AppProperties {

@Value("${env.info:}")
private String envInfo;

}

特别注意

  • Spring Cloud Consul 默认是每隔 55 秒执行一次配置刷新,以此来判断 Consul 配置中心的配置信息是否发生了变更。
  • 如果希望接近实时的更新配置信息,可以通过 spring.cloud.consul.config.watch.wait-time 来指定配置信息更新的时间间隔(单位是秒),但生产环境不建议更改此参数。官方文档的说明如下图所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
spring:
application:
name: cloud-payment-service
cloud:
consul:
host: 127.0.0.1 # Consul 启动地址
port: 8500 # Consul 启动端口
config:
format: YAML # Consul 中 Value 的配置格式为 YAML
prefix: config # Consul 中的配置文件目录,默认为 config
default-context: app # 去该目录下查找缺省配置,默认为 application
profile-separator: '-' # profiles 配置的分隔符,默认为 ','
data-key: data # 如果指定配置格式为 YAML 或者 Properties,则需要该值作为 key,默认为 data
watch:
wait-time: 1 # 配置信息更新的时间间隔(单位是秒),生产环境不建议修改此参数