注册中心篇(四):通过 Consul 集群实现服务注册与发现


由于 Consul 是由 Hashicorp 公司开发的,而这个公司旗下还有一款著名的虚拟化工具 Vagrant,所以这篇教程我们基于 Vagrant 在本地通过虚拟机来演示如何搭建一个包含多个服务端和客户端代理的 Consul 集群。

初始化虚拟机

我们将搭建一个包含两个 Consul Server,一个 Consul Client 的集群环境,前面我们介绍 Consul 原理的时候已经提到过,Server 比较重,负责所有数据的存储并保证一致性,Client 则比较轻量级,只负责健康检查和请求转发,首先我们在本地用户家目录下创建一个 Consul 目录作为 Consul 虚拟机的工作台,然后在该目录下创建一个 Vagrantfile 来存储虚拟机配置信息:

cd ~
mkdir Consul
cd Consul
touch Vagrantfile

然后编辑 Vagrantfile 内容如下(从 https://github.com/hashicorp/consul/blob/master/demo/vagrant-cluster/Vagrantfile 示例文件中拷贝过来粘贴):

# -*- mode: ruby -*-
# vi: set ft=ruby :

$script = <<SCRIPT

echo "Installing dependencies ..."
sudo apt-get update
sudo apt-get install -y unzip curl jq dnsutils

echo "Determining Consul version to install ..."
CHECKPOINT_URL="https://checkpoint-api.hashicorp.com/v1/check"
if [ -z "$CONSUL_DEMO_VERSION" ]; then
    CONSUL_DEMO_VERSION=$(curl -s "${CHECKPOINT_URL}"/consul | jq .current_version | tr -d '"')
fi

echo "Fetching Consul version ${CONSUL_DEMO_VERSION} ..."
cd /tmp/
curl -s https://releases.hashicorp.com/consul/${CONSUL_DEMO_VERSION}/consul_${CONSUL_DEMO_VERSION}_linux_amd64.zip -o consul.zip

echo "Installing Consul version ${CONSUL_DEMO_VERSION} ..."
unzip consul.zip
sudo chmod +x consul
sudo mv consul /usr/bin/consul

sudo mkdir /etc/consul.d
sudo chmod a+w /etc/consul.d

SCRIPT

# Specify a Consul version
CONSUL_DEMO_VERSION = ENV['CONSUL_DEMO_VERSION']

# Specify a custom Vagrant box for the demo
DEMO_BOX_NAME = ENV['DEMO_BOX_NAME'] || "debian/stretch64"

# Vagrantfile API/syntax version.
# NB: Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = DEMO_BOX_NAME

  config.vm.provision "shell",
                          inline: $script,
                          env: {'CONSUL_DEMO_VERSION' => CONSUL_DEMO_VERSION}

  config.vm.define "n1" do |n1|
      n1.vm.hostname = "n1"
      n1.vm.network "private_network", ip: "172.20.20.10"
  end

  config.vm.define "n2" do |n2|
      n2.vm.hostname = "n2"
      n2.vm.network "private_network", ip: "172.20.20.11"
  end
end

接下来,在该目录下运行如下命令初始化并启动上面配置的两个 Consul Server 节点对应的虚拟机(IP 分别为 172.20.20.10172.20.20.11):

vagrant up

vagrant up

如果感觉这种方式下载太慢,可以将其中的链接拷贝出来:https://vagrantcloud.com/debian/boxes/stretch64/versions/9.9.1/providers/virtualbox.box,粘贴到浏览器地址栏然后回车下载,浏览器中下载还是慢的话,就再把浏览器解析出来的下载地址拷贝到下载软件去下载:

下载 Consul 盒子

可以看到,下载速度快了很多,下载完成后,在本地将下载的 box 文件手动添加到 Vagrant 里面,通过 name 选项指定 box 名称,这里的 nameVagrantfile 文件中的 DEMO_BOX_NAME 值保持一致,默认是 debian/stretch64

vagrant box add --name debian/stretch64 /path/to/virtualbox

手动添加盒子到 Vagrant

然后再到 Vagrantfile 所在目录运行 vagrant up 命令,即可快速完成虚拟机安装:

启动虚拟机 ... 启动虚拟机

检查服务端 Consul

安装完成后,我们来检查下虚拟机环境是否符合预期,这里我们只安装了两个虚拟机,用于模拟 Consul Server 服务端节点,而 Consul Client 则运行在本地,与 Go Micro 搭建的微服务部署在一起。

首先运行 vagrant status 查看虚拟机盒子状态,可以看到已经上面安装的两个虚拟机已经运行起来了:

查看虚拟机状态

打开 VirtualBox,也可以在虚拟机列表中看到这两个虚拟机:

在 VirtualBox 中查看虚拟机

接下来,我们分别进入这两个虚拟机,检查 Consul 是否安装成功:

检查 Consul 是否安装成功

启动 Consul Server 集群

从上面的截图中可以看到 Consul 在服务端都已经安装成功,接下来,我们要以 Server 模式启动它们,并将它们组合到同一个数据中心集群,打开两个终端窗口,一个通过 vagrant ssh n1 进入节点 n1,以服务器模式启动 Consul:

consul agent -server -bootstrap-expect=2 \
   -data-dir=/tmp/consul -node=agent-one -bind=172.20.20.10 \
   -config-dir=/etc/consul.d 

启动 Consul Server

另一个通过 vagrant ssh n2 进入节点 n2,同样以服务器模式启动 Consul:

consul agent -server -bootstrap-expect=2 \
    -data-dir=/tmp/consul -node=agent-two -bind=172.20.20.11 \
    -enable-script-checks=true -config-dir=/etc/consul.d

启动 Consul Server

此时,两个服务器节点的 Consul Server 代理都已经运行起来了,但它们还不知道彼此,要将它们加入到一个集群,可以这么做,进入 n1 虚拟机,运行如下命令:

将 Consul Server 加入到一个集群

n2 节点对应的 IP 地址 172.20.20.11 加入进来,这样,运行 consul members 就能看到它们已经处于同一个数据中心了(默认是 dc1):

查看集群中的服务节点

反之,也可以在 n2 上运行该命令,将 IP 地址调整为 n1 节点的 IP 地址即可。

同时可以在 Consul 日志中看到选举 n1 为 Leader 节点(在各自节点上可以通过 consul info 查看明细):

在 Consul 日志中看到选举的 Leader 节点

启动 Consul 客户端代理

接下来,我们回到本地,通过如下命令以 Client 模式启动 Consul 代理:

consul agent -node=agent-client -bind=172.20.20.1 -data-dir=/tmp/consul

以 Client 模式启动 Consul 代理

同样,如果没有加入到集群中,也是看不到其它 Consul 代理的,我们可以通过和服务端一样的方式将其加入到集群中(加入任何一个节点即可),然后就可以看到集群中的所有节点了,包括服务端和客户端 Consul 代理:

查看所有 Consul 节点

这个时候,如果中断 Consul 服务端/客户端代理进程,会导致对应节点状态为 failed,即不可用:

中断客户端代理进程

我们可以带上 -rejoin 选项再次启动中断的节点代理,表示重新加入之前的集群,同时带上 -ui 选项表示启动 Web UI 可视化界面:

consul agent -node=agent-client -bind=172.20.20.1 -data-dir=/tmp/consul -ui -rejoin 

带上 -rejoin 选项再次启动中断的节点代理

再次运行 consul members 命令,可以看到对应节点的 Consul 代理进程已经恢复正常了:

查看所有 Consul 节点

在浏览器中访问 http://localhost:8500/ui/dc1/nodes,可以看到所有有效的节点信息:

在浏览器访问所有 Consul 节点信息

简单测试

接下来,我们简单测试下 Consul 的 KV 存储功能,在客户端机器上运行如下代码:

consul kv put hello world

然后在服务端机器即可访问到对应的存储信息,因为客户端代理并不会做存储和同步,这些请求会转发到服务端,最终由 Leader 完成存储和同步:

consul kv get hello

获取 Consul 存储信息

然后我们来测试下服务注册和发现功能是否正常,在本地启动 Greeter 微服务:

本地启动 Greeter 微服务

服务注册时,同样会经由客户端运行的代理将请求转发给服务端 Leader 节点进行存储和同步,登录到 n1 节点,运行如下命令即可看到对应注册的所有服务:

查看注册服务节点

接下来,在本地运行客户端请求代码:

本地运行客户端请求代码

可以看到,服务发现功能也是 OK 的,这个服务请求同样会经由客户端 Consul 代理转发到服务端代理进行查询,并将服务节点信息返回,再由对应节点运行的微服务进程对请求进行处理和返回。

当然,我们还可以基于 Docker 来模拟 Consul 集群,关于 Docker 编排部分,我们在后面运维部分再详细介绍。


点赞 取消点赞 收藏 取消收藏

<< 上一篇: 注册中心篇(三):Consul 服务发现的底层实现

>> 下一篇: 注册中心篇(五):Etcd 简介和使用入门