Contents

Consul 的领导选举

1. 概述

在本教程中,**我们将了解 Consul 的领导选举如何帮助确保数据稳定性。**我们将提供一个实际示例来说明如何在并发应用程序中管理分布式锁定。

2. 什么是Consul?

Consul 是一个开源工具,提供基于健康检查的服务注册和发现。此外,它还包括一个 Web 图形用户界面 (GUI),用于查看 Consul 并轻松与之交互。它还涵盖了会话管理和键值 (KV) 存储的额外功能。

在接下来的部分中,我们将重点介绍如何使用 Consul 的会话管理和 KV 存储来选择具有多个实例的应用程序中的领导者

3. Consul基础

**Consul 代理 是在 Consul 集群的每个节点上运行的最重要的组件。**负责健康检查;注册、发现和解析服务;存储配置数据;以及更多。

Consul 代理可以在两种不同的模式下运行——服务器和代理。

Consul Server的主要职责是响应来自代理的查询并选举领导者。领导层是使用共识协议 选择的,以提供基于Raft 算法的 一致性(由 CAP 定义)

详细了解共识的工作原理不在本文的范围内。尽管如此,值得一提的是,节点可以处于以下三种状态之一:领导者、候选者或追随者。它还存储数据并响应来自代理的查询。

Agent比 Consul 服务器**更轻量级。**它负责运行注册服务的健康检查并将查询转发到服务器。让我们看一个 Consul 集群的简单示意图:

/uploads/consul_leadership_election/1.jpg

Consul 还可以通过其他方式提供帮助——例如,在一个实例必须是领导者的并发应用程序中。

在接下来的部分中,让我们看看 Consul 如何通过会话管理和 KV 存储来提供这一重要功能。

4. Consul选举

在分布式部署中,持有锁的服务是领导者。因此,对于高可用系统来说,管理锁和领导者是至关重要的。

Consul 提供了一个易于使用的 KV 存储和会话管理 。这些功能用于构建领导者选举 ,所以让我们学习它们背后的原理。

4.1.领导权之争

**属于分布式系统的所有实例所做的第一件事就是争夺领导权。**成为领导者的竞争包括一系列步骤:

  1. 所有实例必须就一个共同的密钥达成一致意见。
  2. 接下来,实例通过 Consul 会话管理和 KV 功能使用约定的密钥创建会话。
  3. 第三,他们应该获得会话。如果返回值为true,则锁属于该实例,如果为false,则该实例是跟随者。
  4. 实例需要持续关注会话以在失败或释放的情况下再次获得领导权
  5. 最后,leader 可以释放会话,过程重新开始。

一旦选举出领导者,其余实例将使用 Consul KV 和会话管理通过以下方式发现领导者:

  • 检索商定的密钥
  • 获取会话信息以了解领导者

4.2. 一个实际的例子

我们需要在运行多个实例的情况下在 Consul 中创建键和值以及会话。为此,我们将使用Kinguin 开源 Java 实现。

首先,让我们包含依赖项:

<dependency>
   <groupId>com.github.kinguinltdhk</groupId>
   <artifactId>leadership-consul</artifactId>
   <version>${kinguinltdhk.version}</version>
   <exclusions>
       <exclusion>
           <groupId>com.ecwid.consul</groupId> 
           <artifactId>consul-api</artifactId>
       </exclusion>
   </exclusions>
</dependency>

我们排除了consul-api依赖项,以避免 Java 中不同版本的冲突。

对于公共密钥,我们将使用:

services/%s/leader

让我们用一个简单的片段来测试所有的过程:

new SimpleConsulClusterFactory()
    .mode(SimpleConsulClusterFactory.MODE_MULTI)
    .debug(true)
    .build()
    .asObservable()
    .subscribe(i -> System.out.println(i));

然后我们使用*asObservable()*创建一个包含多个实例的集群,以方便订阅者访问事件。领导者在 Consul 中创建会话,所有实例验证会话以确认领导。

最后,我们自定义 consul 配置和 session 管理,以及实例间约定的 key 来选举领导者:

cluster:
  leader:
    serviceName: cluster
    serviceId: node-1
    consul:
      host: localhost
      port: 8500
      discovery:
        enabled: false
    session:
      ttl: 15
      refresh: 7
    election:
      envelopeTemplate: services/%s/leader

4.3. 如何测试它

有几个选项可以安装 Consul 和运行代理

部署 Consul 的一种可能性是通过容器 。我们将使用世界上最大的容器镜像存储库 Docker Hub 中提供的Consul Docker 镜像。

我们将通过运行以下命令使用 Docker 部署 Consul:

docker run -d --name consul -p 8500:8500 -e CONSUL_BIND_INTERFACE=eth0 consul

Consul 现在正在运行,它应该在localhost:8500 可用。

让我们执行代码片段并检查完成的步骤:

  1. 领导者在 Consul 中创建一个会话。
  2. 然后它被选举(选举.first)。**
  3. 其余的实例会一直观察直到会话被释放
INFO: multi mode active
INFO: Session created e11b6ace-9dc7-4e51-b673-033f8134a7d4
INFO: Session refresh scheduled on 7 seconds frequency 
INFO: Vote frequency setup on 10 seconds frequency 
ElectionMessage(status=elected, vote=Vote{sessionId='e11b6ace-9dc7-4e51-b673-033f8134a7d4', serviceName='cluster-app', serviceId='node-1'}, error=null)
ElectionMessage(status=elected.first, vote=Vote{sessionId='e11b6ace-9dc7-4e51-b673-033f8134a7d4', serviceName='cluster-app', serviceId='node-1'}, error=null)
ElectionMessage(status=elected, vote=Vote{sessionId='e11b6ace-9dc7-4e51-b673-033f8134a7d4', serviceName='cluster-app', serviceId='node-1'}, error=null)

Consul 还提供了一个 Web GUI,位于http://localhost:8500/ui

让我们打开浏览器并单击键值部分以确认会话已创建:

/uploads/consul_leadership_election/3.jpg

因此,其中一个并发实例使用商定的应用程序密钥创建了一个会话。只有当会话释放后,进程才能重新开始,新的实例才能成为领导者。