1. Overview

1.1 概念

Consul 是 HashiCorp 公司推出的开源工具,Consul 由 Go 语言开发,部署起来非常容易,只需要极少的可执行程序和配置文件,具有绿色、轻量级的特点。Consul 是分布式的、高可用的、 可横向扩展的用于实现分布式系统的服务发现与配置。

1.2 特征

  • 服务发现(Service Discovery):Consul 提供了通过 DNS 或者 HTTP 接口的方式来注册服务和发现服务。一些外部的服务通过 Consul 很容易的找到它所依赖的服务。

  • 健康检查(Health Checking):Consul 的 Client 可以提供任意数量的健康检查,既可以与给定的服务相关联(“webserver是否返回200 OK”),也可以与本地节点相关联(“内存利用率是否低于90%”)。操作员可以使用这些信息来监视集群的健康状况,服务发现组件可以使用这些信息将流量从不健康的主机路由出去。

  • Key/Value 存储:应用程序可以根据自己的需要使用 Consul 提供的 Key/Value 存储。 Consul 提供了简单易用的 HTTP 接口,结合其他工具可以实现动态配置、功能标记、领袖选举等等功能。

  • 安全服务通信:Consul 可以为服务生成和分发 TLS 证书,以建立相互的 TLS 连接。意图可用于定义允许哪些服务通信。服务分割可以很容易地进行管理,其目的是可以实时更改的,而不是使用复杂的网络拓扑和静态防火墙规则。

  • 多数据中心:Consul 支持开箱即用的多数据中心. 这意味着用户不需要担心需要建立额外的抽象层让业务扩展到多个区域。

1.3 使用场景

Consul 的应用场景包括服务发现、服务隔离、服务配置:

  • 服务发现场景中 consul 作为注册中心,服务地址被注册到 consul 中以后,可以使用 consul 提供的 dns、http 接口查询,consul 支持 health check。

  • 服务隔离场景中 consul 支持以服务为单位设置访问策略,能同时支持经典的平台和新兴的平台,支持 tls 证书分发,service-to-service 加密。

  • 服务配置场景中 consul 提供 key-value 数据存储功能,并且能将变动迅速地通知出去,借助 Consul 可以实现配置共享,需要读取配置的服务可以从 Consul 中读取到准确的配置信息。

  • Consul 可以帮助系统管理者更清晰的了解复杂系统内部的系统架构,运维人员可以将 Consul 看成一种监控软件,也可以看成一种资产(资源)管理系统。

1.4 为什么使用服务发现

  • 一般的说法是因为使用微服务架构。传统的单体架构不够灵活不能很好的适应变化,从而向微服务架构进行转换,而伴随着大量服务的出现,管理运维十分不便,于是开始搞一些自动化的策略,服务发现应运而生。所以如果需要使用服务发现,你应该有一些对服务治理的痛点。

  • 但是引入服务发现就可能引入一些技术栈,增加系统总体的复杂度,如果你只有很少的几个服务,比如10个以下,并且业务不怎么变化,吞吐量预计也很稳定,可能就没有必要使用服务发现。

2. 原理图解

2.1 Consul 内部架构图解

微服务注册发现:Consul 介绍 - 图1

  • 首先 Consul 支持多数据中心,在上图中有两个 DataCenter,他们通过 Internet 互联,同时请注意为了提高通信效率,只有 Server 节点才加入跨数据中心的通信。

  • 在单个数据中心中,Consul 分为 Client 和 Server 两种节点(所有的节点也被称为 Agent),Server 节点保存数据,Client 负责健康检查及转发数据请求到 Server;Server 节点有一个 Leader 和多个 Follower,Leader 节点会将数据同步到 Follower.

    • Server 的数量推荐是3个或者5个,这在故障情况下对可用性和性能之间取得了平衡,因为随着添加更多的机器,一致性会逐渐变慢。
    • 但是,Client 的数量没有限制,可以很容易扩展到数千或数万。
    • 在 Leader 挂掉的时候会启动选举机制产生一个新的 Leader。
  • 集群内的 Consul 节点通过 gossip 协议(流言协议)维护成员关系,也就是说某个节点了解集群内现在还有哪些节点,这些节点是 Client 还是 Server。单个数据中心的流言协议同时使用 TCP 和 UDP 通信,并且都使用 8301 端口。跨数据中心的流言协议也同时使用 TCP 和 UDP 通信,端口使用 8302。

    • 使用 gossip 协议不需要使用服务器的地址来配置客户端,服务发现是自动完成;
    • 健康检查故障的工作不是放在 Server 上,而是分布式在 Client 上的。这使得故障检测比单纯的心跳模式更具可伸缩性。
  • 集群内数据的读写请求既可以直接发到 Server,也可以通过 Client 使用 RPC 转发到 Server,请求最终会到达 Leader 节点,在允许数据轻微陈旧的情况下,读请求也可以在普通的 Server 节点完成,集群内数据的读写和复制都是通过 TCP 的 8300 端口完成。

  • Consul 集群中常见概念总结:

    • Gossip:Gossip protocol 也叫 Epidemic Protocol (流言协议), 这个协议的作用就像其名字表示的意思一样,它的方式在我们日常生活中也很常见,比如电脑病毒的传播,森林大火,细胞扩散等等。
    • Client:Client 是一个转发所有 RPC 到 server 的代理。这个 client 是相对无状态的。client 唯一执行的后台活动是加入 LAN gossip 池。这有一个最低的资源开销并且仅消耗少量的网络带宽。
    • Server:Server 是一个有一组扩展功能的代理,这些功能包括参与 Raft 选举,维护集群状态,响应 RPC 查询,与其他数据中心交互 WAN gossip 和转发查询给 leader 或者远程数据中心。
    • DataCenter:虽然数据中心的定义是显而易见的,但是有一些细微的细节必须考虑。例如,在 EC2 中,多个可用区域被认为组成一个数据中心。我们定义数据中心为一个私有的,低延迟和高带宽的一个网络环境。这不包括访问公共网络,但是对于我们而言,同一个 EC2 中的多个可用区域可以被认为是一个数据中心的一部分。
    • Consensus:一致性,使用 Consensus 来表明就 leader 选举和事务的顺序达成一致。为了以容错方式达成一致,一般有超过半数一致则可以认为整体一致。Consul 使用 Raft 实现一致性,进行 leader 选举,在 consul 中的使用 bootstrap 时,可以进行自选,其他 server 加入进来后 bootstrap 就可以取消。
    • LAN Gossip:它包含所有位于同一个局域网或者数据中心的所有节点。
    • WAN Gossip:它只包含 Server。这些 server 主要分布在不同的数据中心并且通常通过因特网或者广域网通信。
    • RPC:远程过程调用。这是一个允许 client 请求 server 的请求/响应机制。

2.2 Consul 服务发现图解

微服务注册发现:Consul 介绍 - 图2

  • 首先需要有一个正常的 Consul 集群,有 Server,有 Leader。这里在服务器物理机 Server1、Server2、Server3 上分别部署了 Consul Server,假设他们选举了物理机 Server2 上的 Consul Server 节点为 Leader。这些服务器上最好只部署 Consul 程序,以尽量维护 Consul Server 的稳定。

  • 然后在物理机 Server4 和 Server5 上通过 Consul Client 分别注册 Service A、B、C,这里每个 Service 分别部署在了两个服务器上,这样可以避免 Service 的单点问题。服务注册到 Consul 可以通过 HTTP API(8500端口)的方式,也可以通过 Consul 配置文件的方式。Consul Client 可以认为是无状态的,它将注册信息通过 RPC 转发到 Consul Server,服务信息保存在 Server 的各个节点中,并且通过 Raft 实现了强一致性。

  • 最后在服务器 Server6 中 Service D 需要访问 Service B,这时候 Service D 首先访问本机 Consul Client 提供的HTTP API,本机 Client 会将请求转发到 Consul Server,Consul Server 查询到 Service B 当前的信息返回,最终 Service D拿到了 Service B 的所有部署的 IP 和端口,然后就可以选择 Service B 的其中一个部署并向其发起请求了。如果服务发现采用的是 DNS 方式,则 Service D 中直接使用 Service B 的服务发现域名,域名解析请求首先到达本机 DNS 代理,然后转发到本机 Consul Client,本机 Client 会将请求转发到 Consul Server,Consul Server 查询到 Service B 当前的信息返回,最终 Service D 拿到了 Service B 的某个部署的 IP 和端口。

  • 图中描述的部署架构是最普适最简单的方案,从某些默认配置或设计上看也是官方希望使用者采用的方案,比如 8500 端口默认监听 127.0.0.1。

3. Consul 与其他框架差异

3.1 综合比较 euerka/consul/zookeeper/etcd

image.png

3.1 Consul VS Eureka

Eureka 是一个服务发现工具。该体系结构主要是 Client/Server,每个数据中心有一组 Eureka 服务器,通常每个可用区域一个。通常 Eureka 的 Client 使用嵌入式 SDK 来注册和发现服务。对于非本地集成的 Client,官方提供了 Eureka 一些 REST 操作 API,其它语言可以使用这些 API 来实现对 Eureka Server 的操作从而实现一个非 jvm 语言的 Eureka Client。

Eureka 提供了一个弱一致的服务视图,尽可能的提供服务可用性。当 Client 向 Server 注册时,该 Server 将尝试复制到其它 Server,但不提供保证复制完成。服务注册的生存时间(TTL)较短,要求 Client 对 Server 心跳检测。不健康的服务或节点停止心跳,导致它们超时并从注册表中删除。服务发现可以路由到注册的任何服务,由于心跳检测机制有时间间隔,可能会导致部分服务不可用。这个简化的模型允许简单的群集管理和高可扩展性。

Consul 提供了一些列特性,包括更丰富的健康检查,键值对存储以及多数据中心。Consul 需要每个数据中心都有一套服务,以及每个客户端的 agent,类似于使用像 Ribbon 这样的服务。Consul agent 允许大多数应用程序成为 Consul 不知情者,通过配置文件执行服务注册并通过 DNS 或负载平衡器 sidecars 发现。

Consul 提供强大的一致性保证,因为服务器使用 Raft 协议复制状态 。Consul 支持丰富的健康检查,包括 TCP,HTTP,Nagios / Sensu 兼容脚本或基于 Eureka 的 TTL。客户端节点参与基于 Gossip 协议的健康检查,该检查分发健康检查工作,而不像集中式心跳检测那样成为可扩展性挑战。发现请求被路由到选举出来的 leader,这使他们默认情况下强一致性。允许客户端过时读取取使任何服务器处理他们的请求,从而实现像 Eureka 这样的线性可伸缩性。

Consul 强烈的一致性意味着它可以作为领导选举和集群协调的锁定服务。Eureka 不提供类似的保证,并且通常需要为需要执行协调或具有更强一致性需求的服务运行 ZooKeeper。

Consul 提供了支持面向服务的体系结构所需的一系列功能。这包括服务发现,还包括丰富的运行状况检查,锁定,密钥/值,多数据中心联合,事件系统和 ACL。Consul 和 consul-template 和 envconsul 等工具生态系统都试图尽量减少集成所需的应用程序更改,以避免需要通过 SDK 进行本地集成。

Eureka 是一个更大的 Netflix OSS 套件的一部分,该套件预计应用程序相对均匀且紧密集成。因此 Eureka 只解决了一小部分问题,可以和 ZooKeeper 等其它工具可以一起使用。

Consul 强一致性(C)带来的是:
服务注册相比 Eureka 会稍慢一些。因为 Consul 的 raft 协议要求必须过半数的节点都写入成功才认为注册成功 Leader 挂掉时,重新选举期间整个 Consul 不可用。保证了强一致性但牺牲了可用性。

Eureka 保证高可用(A)和最终一致性:
服务注册相对要快,因为不需要等注册信息 replicate 到其它节点,也不保证注册信息是否 replicate 成功 当数据出现不一致时,虽然 A, B 上的注册信息不完全相同,但每个 Eureka 节点依然能够正常对外提供服务,这会出现查询服务信息时如果请求 A 查不到,但请求 B 就能查到。如此保证了可用性但牺牲了一致性。

其它方面,eureka 就是个 servlet 程序,跑在 servlet 容器中; Consul 则是 go 编写而成。

参考链接: https://www.consul.io/docs/intro https://www.imooc.com/article/296209/ https://www.nodejs.red/#/microservice/consul