服务发现组件:Consul简易攻略

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
云解析DNS,个人版 1个月
简介: 本篇作为Consul攻略的入门导引,帮助小伙伴了解Consul全貌,包含特性、命令操作、架构原理、介绍了Raft、Gossip协议等。

简介


  Consul是一种分布式、高可用性、支持多数据中心的解决方案,可动态、分布式基础架构连接和配置的应用程序。


特性


  • 『多数据中心』

    Consul是为支持数据中心而构建的,可以支持任意数量的区域,而无需复杂的配置。
  • 『服务网格』

    Consul服务网格通过自动TLS加密和基于身份的授权实现安全的服务到服务通信。应用程序可以在服务网格配置中使用sidecar代理,通过透明代理为入站和出站连接建立TLS连接。
  • 『服务发现』

    Consul使服务注册自己和通过DNSHTTP接口发现其他服务变得简单。SaaS提供商等外部服务也可以注册。
  • 『健康检查』

     健康检查使Consul能够快速提醒和反馈集群中的任何问题,与服务发现的集成可防止将流量路由到不健康的主机,并启用服务级别断路器。
  • 『键值对存储』

     灵活的键值对存储器支持存储动态配置、功能标记、协调、Leader选举等。简单的HTTP API使其易于在任何地方使用。


  Consul支持在Linux、macOS、FreeBSD、Solaris、Windows系统上运行,提供了交互友好的Web UI管理,也提供了Consul Enterprise的商业版本。


环境安装


MacOS系统,依赖xcode版本,不符合的可以升级下版本


brew tap hashicorp/tap

brew install hashicorp/tap/consul


Consul使用


  关于Consul的使用主要可以通过两种途径完成,一种通过原生支持的WebUI进行可视化管理,另一种是通过API、Command(Cli)能力实现交互。


途径

备注

WebUI

Consul服务启动后访问 http://{ip}:8500/ui

API、Command(Cli)

Consul Command(Cli)

API


Command(Cli)


  如下是Consul支持的命令清单,关于命令集操作大部分都是开源版本支持的,部分是需要商业版才可以支持,这里只关注开源版常用命令。


命令

说明

acl

访问控制交互

agent

运行Consul的代理

catalog

目录交互

connect

Consul连接相关

debug

支持debug模式调试

event

启动一个新事件

exec

在Consul节点上执行命令

force-leave

强制集群成员进入“left”状态

info

提供调试信息

intention

交互连接服务意向

join

通知Consul代理加入集群

keygen

生成新的加密密钥

keyring

管理gossip层的加密密钥

kv

交互KV存储

leave

优雅地离开Consul集群并关闭

lock

执行持有锁的命令

login

使用身份验证方法登录Consul

logout

销毁使用登录创建的Consul令牌

maint

控制节点或服务维护模式

members

输出Consul集群中的节点信息

monitor

从Consul代理流式传输日志

operator

提供操作集群的工具

peering

创建、管理Consul集群之间的对等连接

reload

触发代理重新加载配置文件

rtt

评估节点之间的网络往返时间

services

和服务进行交互

snapshot

保存、恢复和检查Consul服务器状态的快照

tls

用于创建CA和证书的内置帮助程序

validate

验证配置文件/目录

version

输出Consul版本

watch

监听Consul变化


  下面我们通过串联实际案例体验下核心的Command(Cli)API来操作交互,如下:


查看版本


  当安装完成后,可以执行如下查看当前Consul版本号,这里我们使用的当前最新的v1.14.2版本。


[parallels@localhost bin]$ ./consul --version


Consul v1.14.2

Revision 0ba7a401

Build Date 2022-11-30T19:54:31Z

Protocol 2 spoken by default, understands 2 to 3 (agent will automatically use protocol >2 when speaking to compatible agents)


服务启动


  服务启动可以通过debug、server模式来进行。


  debug模式下,可以支持单节点启动,适合本地测试,不需要多服务器节点来搭建集群。


# -server 以服务模式启动

# -bind 绑定服务IP

# -client 允许所有IP访问

# -ui 打开可视化页面

# -data-dir 数据存储路径

# -node 节点名称

[parallels@localhost bin]$ ./consul agent -dev -bind=192.168.0.101 -client=0.0.0.0 -ui -data-dir=/usr/local/consul/data/ -node=server-01


  server模式下,需要最少3个节点共同支持方可完成启动。


  为了避免网络通信产生问题,可先关闭服务器防火墙设置,如下:


systemctl stop firewalld

systemctl disable firewalld


  这里准备了三台服务器10.211.55.3110.211.55.3210.211.55.33,分别以Server模式启动,如下:


# -server 以服务模式启动

# -bind 绑定服务IP

# -client 允许所有IP访问

# -ui 打开可视化页面

# -bootstrap-expect 集群节点数量,最少3个,最多建议5个

# -data-dir 数据存储路径

# -node 节点名称

[parallels@localhost bin]$ ./consul agent -server -bind=10.211.55.31 -client=0.0.0.0 -ui -bootstrap-expect=3 -data-dir=/usr/local/consul/data/ -node=server-01

[parallels@localhost bin]$ ./consul agent -server -bind=10.211.55.32 -client=0.0.0.0 -ui -bootstrap-expect=3 -data-dir=/usr/local/consul/data/ -node=server-02

[parallels@localhost bin]$ ./consul agent -server -bind=10.211.55.33 -client=0.0.0.0 -ui -bootstrap-expect=3 -data-dir=/usr/local/consul/data/ -node=server-03


  启动后的Server节点并不会自动完成Leader选举,需要完成join命令操作完成加入操作,这里让10.211.55.31成为Leader,需要在10.211.55.3210.211.55.33机器上执行如下命令进行加入,如下:


[parallels@localhost bin]$ ./consul join 10.211.55.31


查看集群成员信息


  当加入完节点后,我们再来查看下当前集群的成员信息,可以看到节点名称、地址端口、节点状态、节点类型、机房等信息。


[parallels@localhost bin]$ ./consul members


Node       Address            Status  Type    Build   Protocol  DC   Partition  Segment

server-01  10.211.55.31:8301  alive   server  1.14.2  2         dc1  default    <all>

server-02  10.211.55.32:8301  alive   server  1.14.2  2         dc1  default    <all>

server-03  10.211.55.33:8301  alive   server  1.14.2  2         dc1  default    <all>


Raft视角相关操作


  由于Consul集群是基于Raft协议来构建的,Cli操作也提供了Raft视角的一些查看、处理操作。


### 可以看到10.211.55.31当前是leader节点,其余两个是follower节点


[parallels@localhost bin]$ ./consul operator raft list-peers


Node       ID                                    Address            State     Voter  RaftProtocol

server-03  996beb1a-ffa3-a621-d384-e355a1edeb37  10.211.55.33:8300  leader    true   3

server-01  0c117b67-d283-6b5d-98bd-217d829cda9e  10.211.55.31:8300  follower  true   3

server-02  0fb2224a-0ad4-7053-1bea-0c89a408d569  10.211.55.32:8300  follower  true   3


### 指定IP+PORT踢出节点不再参与Raft协议过程,适合处理节点异常的情况

consul operator raft remove-peer -address=10.211.55.33:8300


Removed peer with address "10.211.55.33:8300"


查看目录信息


### 节点信息

[parallels@localhost bin]$ ./consul catalog nodes

Node       ID        Address       DC

server-01  0c117b67  10.211.55.31  dc1

server-02  0fb2224a  10.211.55.32  dc1

server-03  996beb1a  10.211.55.33  dc1


### 服务信息

[parallels@localhost bin]$ ./consul catalog services

consul


### 数据中心、机房信息

[parallels@localhost bin]$ ./consul catalog datacenters

dc1


查看Consul元数据


  提供了Consul运维管理层面的元数据查看能力


### - agent: 提供agent相关信息

### - consul: 提供当前节点的Consul信息

### - raft: 提供Raft一致性协议信息 (https://developer.hashicorp.com/consul/docs/architecture/consensus)

### - serf_lan:提供本地局域网Gossip协议信息 (https://developer.hashicorp.com/consul/docs/architecture/gossip)

### - serf_wan:提供广域网Gossip协议信息(https://developer.hashicorp.com/consul/docs/architecture/gossip)


[parallels@localhost bin]$ ./consul info


agent:

check_monitors = 0

check_ttls = 0

checks = 0

services = 0

build:

prerelease =

revision = 0ba7a401

version = 1.14.2

version_metadata =

consul:

acl = disabled

bootstrap = false

known_datacenters = 1

leader = false

leader_addr = 10.211.55.31:8300

server = true

raft:

applied_index = 47

commit_index = 47

fsm_pending = 0

last_contact = 78.947472ms

last_log_index = 47

last_log_term = 2

last_snapshot_index = 0

last_snapshot_term = 0

latest_configuration = [{Suffrage:Voter ID:0c117b67-d283-6b5d-98bd-217d829cda9e Address:10.211.55.31:8300} {Suffrage:Voter ID:0fb2224a-0ad4-7053-1bea-0c89a408d569 Address:10.211.55.32:8300} {Suffrage:Voter ID:996beb1a-ffa3-a621-d384-e355a1edeb37 Address:10.211.55.33:8300}]

latest_configuration_index = 0

num_peers = 2

protocol_version = 3

protocol_version_max = 3

protocol_version_min = 0

snapshot_version_max = 1

snapshot_version_min = 0

state = Follower

term = 2

runtime:

arch = amd64

cpu_count = 2

goroutines = 126

max_procs = 2

os = linux

version = go1.19.2

serf_lan:

coordinate_resets = 0

encrypted = false

event_queue = 0

event_time = 2

failed = 0

health_score = 0

intent_queue = 0

left = 0

member_time = 3

members = 3

query_queue = 0

query_time = 1

serf_wan:

coordinate_resets = 0

encrypted = false

event_queue = 0

event_time = 1

failed = 0

health_score = 0

intent_queue = 0

left = 0

member_time = 3

members = 3

query_queue = 0

query_time = 1


操作KV存储


  构建完集群后我们来向Consul中做KV数据操作,如下:


### 存储key为user,value为zhangsan的数据

[parallels@localhost bin]$ ./consul kv put user zhangsan

Success! Data written to: user


### 查看当前KV数据,value存储格式是base64

[parallels@localhost bin]$ ./consul kv export

[

{

"key": "user",

"flags": 0,

"value": "emhhbmdzYW4="

}

]


### 指定key查看数据

[parallels@localhost bin]$ ./consul kv get user

zhangsan


### 指定key删除数据

[parallels@localhost bin]$ ./consul kv delete user

Success! Deleted key: user


查看节点间延迟


  可以检查节点之间的网络延迟情况。


### 查看server-01 server-02之间

[parallels@localhost bin]$ ./consul rtt server-01 server-02

Estimated server-01 <-> server-02 rtt: 1.235 ms (using LAN coordinates)

### 查看server-01 server-03之间

[parallels@localhost bin]$ ./consul rtt server-01 server-03

Estimated server-01 <-> server-03 rtt: 1.261 ms (using LAN coordinates)

### 查看server-02 server-03之间

[parallels@localhost bin]$ ./consul rtt server-02 server-03

Estimated server-02 <-> server-03 rtt: 1.157 ms (using LAN coordinates)


注册注销服务


### 注册client-01服务

[parallels@localhost bin]$ ./consul services register -name=client-01

Registered service: client-01

### 查看服务列表

[parallels@localhost bin]$ ./consul catalog services

client-01

consul

### 注销client-01服务

[parallels@localhost bin]$ ./consul services deregister -id=client-01

Deregistered service: client-01

### 查看服务列表

[parallels@localhost bin]$ ./consul catalog services

consul


监听器使用


  监听器支持如下形式监听:


  • key - 监听指定键值对
  • keyprefix - 监控指定键前缀
  • services - 监听service服务列表
  • nodes - 监听nodes节点列表
  • service- 监听service实例
  • checks - 监听健康检查
  • event - 监听用户事件


  下面演示监听指定key变化:


### 先创建一个sh脚本,内容为 echo 'key is changed'

[root@localhost bin]# touch shell.sh


### 配置监听key为user的命令,该key变化后会执行shell.sh脚本,此时会挂起

[root@localhost bin]# ./consul watch -type=key -key=user /usr/local/bin/shell.sh


### 修改key为user的值

[parallels@localhost bin]$ ./consul kv put user lisi

Success! Data written to: user


### 监听到key的变化调用shell.sh

[root@localhost bin]# ./consul watch -type=key -key=user /usr/local/bin/shell.sh

key is changed


API


  API的交互调试,推荐使用PostmanHttp工具,API的功能和Command(Cli)提供的能力相仿,可参考文档自行测试。Consul API


源码解读


架构概览


网络异常,图片无法展示
|


  上图是Consul官方提供的架构示意图,解读如下:


  • 支持多机房部署,跨机房通过局域网Gossip协议进行通信
  • 每个机房有多个Client、Server模块构成,职责如下
  • Client: 客户端,无状态,将Http/DNS接口请求转发给局域网内的服务端集群,主要作用是做服务代理进行请求转发,和具体服务进行交互,在大规模集群下很快就会膨胀到成千上万个。
  • Server: 服务端,保持配置信息,高可用集群,每个数据中心的server数量推荐为3个或者5个,通过Raft协议进行通信,是CP的实现,极端情况下保证数据一致性牺牲可用性。


源码结构


如果觉得每个模块的源码太多,梳理不清楚逻辑关系,可参考Goland中使用GoPlantUml生成ER关系图 进行ER图拆解。


  首先,将1.4.2版本代码结构整理成了思维导图,绿色背景模块是个人认为较为重要的目录,学习时可以重点关注。


网络异常,图片无法展示
|


功能特性


  工程目录中contributing、docs两个目录文档内容是非常好的Consul源码学习材料,它能有效地引导我们快速认识Consul


  • contributing是概括性内容,便于了解全貌。
  • docs是每个模块详细介绍,便于了解细节。


  下面我们借助两个目录文档内容来剖析下Consul的核心功能模块,如下:


网络异常,图片无法展示
|


模块

介绍

Command-Line Interface (CLI)

- 基于https://github.com/mitchellh/cli 实现的命令行交互工具,这部分的核心代码在目录command

中,可以在main.go

查看Cli

的启动进行溯源跟踪。

HTTP API

- 这部分的核心代码在目录api

中,使用了Go

官方的API

库,Consul

CLI

命令也使用该客户端与本地Consul

代理进行通信。

Agent Configuration

- 代理配置是配置Consul

的主要机制。代理配置还允许指定代理启动时将加载的配置条目、服务和检查。
- 大多数配置来自hcl

json

文件,但也可以使用命令行标志指定某些配置,也可以使用Auto Config

加载某些配置。
- 这部分核心代码在目录agent/config

RPC

-Consul

使用两个RPC

系统在集群内的组件之间以及其他客户端之间进行通信,gRPC

Go

net/RPC

包。
- 客户端代理和服务器之间的通信混合使用gRPC

net/rpc

。一般来说,gRPC

是首选的,因为它支持诸如上下文、截止日期、取消、流和中间件等功能,但Consul

已经存在了一段时间,因此大多数RPC

端点仍然使用net/RPC

。大多数集群内通信都是通过多路复用的“服务器”TCP

端口进行的(默认值:8300)。Consul

服务器实现了一个自定义协议,用于在同一端口上服务不同类型的流量,其中发送的第一个字节表示协议(例如gRPC

net/rpc

Raft

)。在单个服务器端口上复用多个协议有助于减少网络需求,但也让使用grpcurl

等本地开发工具与Consul

进行交互变得困难。
- 这部分的核心代码在目录agent/consul/rpc.go

Cluster Persistence

- 集群持久化子系统完全在服务器代理中运行。它处理来自RPC

子系统的读和写请求。
- 有关Consul

部署体系结构和集群持久化子系统使用的共识协议的介绍,可以参阅Consul

体系结构指南。
- 这部分主要是基于Raft

共识协议实现

Client Agent

客户端代理核心代码主要有以下部分:
- agent/cache
- agent/local

- agent/ae

客户端节点上的应用程序在客户端模式下使用其本地代理来注册服务,并发现其他服务或与密钥/值存储交互

Service Discovery

服务发现包含如下部分:
- Catalog,是服务发现和服务网格的核心。它接受服务、节点和检查的注册和注销。
- DNS Interface,DNS接口允许用户使用DNS查询查找服务的IP地址和端口,DNS接口在许多方面类似于HTTP API,主要区别在于DNS协议的不同。
- Health Checks

Service Mesh (Connect)

服务网格

Cluster Membership

集群成员关系包含如下:
- hashicorp/serf
- hashicorp/memberlist
- network coordinates
- consul events
- consul exec
客户机和服务器模式代理都参与Gossip

协议,该协议提供了两种重要机制。
- 首先,它允许代理了解集群中的所有其他代理,只需最初加入集群的单个现有成员即可。这允许客户端发现新的Consul

服务器。
- 其次,Gossip

协议提供了一个分布式故障检测器,集群中的代理以规则的间隔随机探测彼此。由于有了这个故障检测器,Consul

可以在每个代理上本地运行运行状况检查,并在运行状况检查的状态发生变化时发送边缘触发的更新,确信如果代理完全死亡,那么集群将检测到这一点。这使得Consul

的健康检查设计与具有中央轮询类型设计的集中式系统相比非常可扩展。

Key/Value Store

KV存储相关

ACL

ACL

子系统负责验证和授权对Consul

操作HTTP-API

RPC

的访问。

Multi-Cluster Federation

这部分主要是企业版功能


协议


  在Consul中,数据一致性使用到Raft协议完成,节点通信使用到Gossip协议完成。可以说一致性协议、通信协议两大协议簇撑起了分布式服务及其组件的理论基础和技术底盘,类似的还有Redis、Kafka、RocketMQ等。


协议

实现

作用

Raft

基于HashiCorp自己的https://github.com/hashicorp/raft

数据一致性管理,协商、投票、Leader选举等

Gossip

基于HashiCorp自己的 https://www.serf.io/

实现

集群节点通信,处理节点发现、故障检测等


  在这里真的很佩服hashicorp这家公司,大家感兴趣可以在在Github上找到该公司的开源库。


Raft协议

Consul一致性协议介绍


Raft和FSM


  hashicorp/raft是集群持久性的核心。Raft需要FSM(一种有限状态机实现)来持久化状态更改。Consul FSM作为一组命令的核心代码在目录agent/consul/fsm


  Raft还需要LogStore将日志持久化到磁盘。Consul使用hashicorp/raft-boltdb,它使用boltdb.实现LogStore。在不久的将来,推荐使用bbolt


状态存储


  Consul使用状态存储将集群的完整状态存储在内存中。状态存储在agent/consul/state实现,并使用hashicorp/go-memdb维护存储在一组表中的数据索引,状态存储的主要入口点是NewStateStore


表/结构/索引


  状态存储被组织为一组表,每个表都有一组索引。架构中的schema.go显示表的完整列表,每个模式函数显示索引的完整列表。


  定义表索引有两种样式。原始样式使用来自hashicorp/go-memdb(例如StringFieldIndex)的通用索引器实现。这些索引使用reflect查找索引的值。当索引值是直接从struct字段中获得的单个值,并且没有oss/enterprise差异时,这些通用索引器工作得很好。


  第二种类型的索引器是仅使用函数并基于indexer.go中定义的类型实现的自定义索引器。当索引值是从一个或多个字段派生的值时,或者当索引之间存在oss/enterprise差异时,这种类型的索引非常有效。


快照/恢复


  快照(snapshot) 是用于备份集群持久性存储的数据的主要机制。如果所有Consul服务器都出现故障,则可以使用快照将群集恢复到以前的状态。


  需要注意的是,在不同的层中存在两种不同的快照和恢复概念。首先是raftFSM接口上的SnapshotRestore方法,Consul必须实现这些方法。这些方法主要通过状态存储来实现。这些方法可以由raft内部调用,以执行日志压缩(快照)或引导新的跟随器(恢复)。Consul的快照和还原类型实现快照和还原的核心代码在agent/consul/state


  快照和还原也作为用户可以执行的操作存在。有CLI命令、HTTP API端点和RPC端点,允许用户捕获包含状态快照的存档,并将该状态还原到正在运行的集群。consul/snapshot为用户创建和读取快照存档提供了一些逻辑。有关这些面向用户的操作的参考,请参见consul/snapshot


  最后,还有一个快照代理(仅限企业版),它使用快照API端点定期捕获快照,并可选择将其发送到某个存储位置。


Gossip协议


Consul Gossip协议介绍


网络异常,图片无法展示
|


  Consul使用LAN Gossip PoolWAN Gossip Pool来执行不同的功能。这些协议池能够通过利用嵌入式Serf库来执行其功能。Consul对库进行了抽象和屏蔽,以简化用户体验和操作的复杂度。


局域网通信池(LAN Gossip Pool)


  Consul所在的每个数据中心都有一个包含数据中心所有成员(客户端和服务器)的LAN Gossip PoolLAN Gossip Pool提供的成员信息允许客户端自动发现服务器,从而减少所需的配置量。故障检测也由整个集群分布和共享,而不是集中在几个服务器上,LAN Gossip Pool可以快速可靠的进行事件广播。


广域网通信池(WAN Gossip Pool)


  WAN Gossip Pool是全球唯一的,无论数据中心如何,所有服务器都应参与WAN Gossip PoolWAN Gossip Pool提供的成员信息允许服务器执行跨数据中心请求。集成故障检测允许Consul优雅地处理连接丢失,无论是整个数据中心还是远程数据中心中的单个服务器。


参考资料

目前最新版本为1.4.2,本篇以此版本为参考。

Consul官网
Consul官方文档
Github源码地址
简易的入门视频

相关文章
|
9月前
|
Go 数据中心 微服务
Golang 语言微服务的服务发现组件 Consul 的系统架构介绍
Golang 语言微服务的服务发现组件 Consul 的系统架构介绍
70 0
|
9月前
|
存储 安全 Go
Golang 语言微服务的服务注册与发现组件 Consul
Golang 语言微服务的服务注册与发现组件 Consul
72 0
|
9月前
|
Prometheus 监控 Cloud Native
Prometheus基于consul服务发现
Prometheus基于consul服务发现
|
11月前
|
存储 Java 数据中心
|
12月前
|
缓存 中间件 开发工具
go-micro使用Consul做服务发现的方法和原理
go-micro使用Consul做服务发现的方法和原理
172 0
|
存储 负载均衡 Kubernetes
配置管理和服务发现之Confd和Consul
配置管理和服务发现之Confd和Consul
180 0
|
存储 负载均衡 监控
SpringCloud Day02---服务发现与注册(Eureka+zookeeper+Consul(四)
SpringCloud Day02---服务发现与注册(Eureka+zookeeper+Consul
SpringCloud Day02---服务发现与注册(Eureka+zookeeper+Consul(四)
|
JSON 安全 Java
SpringCloud Day02---服务发现与注册(Eureka+zookeeper+Consul(三)
SpringCloud Day02---服务发现与注册(Eureka+zookeeper+Consul
SpringCloud Day02---服务发现与注册(Eureka+zookeeper+Consul(三)
|
缓存 负载均衡 网络协议
SpringCloud Day02---服务发现与注册(Eureka+zookeeper+Consul(二)
SpringCloud Day02---服务发现与注册(Eureka+zookeeper+Consul)
SpringCloud Day02---服务发现与注册(Eureka+zookeeper+Consul(二)
|
存储 负载均衡 监控
SpringCloud Day02---服务发现与注册(Eureka+zookeeper+Consul)
SpringCloud Day02---服务发现与注册(Eureka+zookeeper+Consul)
SpringCloud Day02---服务发现与注册(Eureka+zookeeper+Consul)