SpringCloud学习总结——服务注册中心Consul

Posted tvvt-kevin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringCloud学习总结——服务注册中心Consul相关的知识,希望对你有一定的参考价值。

案例准备

用例spring_cloud_consul 项目地址:传送门

 

Eureka替换方案Consul

 

一、Eureka闭源影响

技术图片

 

 

 

在Euraka的GitHub上,宣布Eureka 2.x闭源。近这意味着如果开发者继续使用作为 2.x 分支上现有工作 repo 一部分发布的代码库和工件,则将自负风险。

Eureka的替换方案

Zookeeper

ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。

Consul consul是近几年比较流行的服务发现工具,工作中用到,简单了解一下。consul的三个主要应用场景:服务发现、服务隔离、服务配置。

Nacos Nacos 是阿里巴巴推出来的一个新开源项目,这是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。 Nacos 是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。

 

二、什么是consul

consul 概述

consul官网

技术图片

 

 

 

Consul 是 HashiCorp 公司推出的开源工具,用于实现分布式系统的服务发现与配置。与其它分布式服务注册与发现的方案,Consul 的方案更“一站式”,内置了服务注册与发现框 架、分布一致性协议实现、健康检查、Key/Value 存储、多数据中心方案,不再需要依赖其它工具(比如 ZooKeeper 等)。使用起来也较 为简单。Consul 使用 Go 语言编写,因此具有天然可移植性(支持Linux、windows和Mac OS X);安装包仅包含一个可执行文件,方便部署,与 Docker 等轻量级容器可无缝配合。

Consul 的优势:

  • 使用 Raft 算法来保证一致性, 比复杂的 Paxos 算法更直接. 相比较而言, zookeeper 采用的是Paxos, 而 etcd 使用的则是 Raft。

  • 支持多数据中心,内外网的服务采用不同的端口进行监听。 多数据中心集群可以避免单数据中心的单点故障,而其部署则需要考虑网络延迟, 分片等情况等。 zookeeper 和 etcd 均不提供多数据中心功能的支持。

  • 支持健康检查。 etcd 不提供此功能。

  • 支持 http 和 dns 协议接口。 zookeeper 的集成较为复杂, etcd 只支持 http 协议。

  • 官方提供 web 管理界面, etcd 无此功能。

  • 综合比较, Consul 作为服务注册和配置管理的新星, 比较值得关注和研究。

特性:

  • 服务发现

  • 健康检查

  • Key/Value 存储

  • 多数据中心

 

consul与Eureka的区别

(1)一致性

Consul强一致性(CP)

  • 服务注册相比Eureka会稍慢一些。因为Consul的raft协议要求必须过半数的Consul节点都写入成功才认为注册成功

  • Leader挂掉时,重新选举期间整个consul不可用。保证了强一致性但牺牲了可用性。

Eureka保证高可用和最终一致性(AP)

  • 服务注册相对要快,因为不需要等注册信息replicate到其他节点,也不保证注册信息是否replicate成功

  • 当数据出现不一致时,虽然Eureka节点 A, B上的注册信息不完全相同,但每个Eureka节点依然能够正常对外提供服务,这会出现查询服务信息时如果请求A查不到,但请求B就能查到。如此保证了可用性但牺牲了一致性。

(2)开发语言和使用

  • eureka就是个servlet程序,跑在servlet容器中

  • Consul则是go编写而成,安装启动即可

 

consul的下载与安装

Consul 不同于 Eureka 需要单独安装,访问 Consul 官网下载 Consul 的最新版本,我这里是consul1.5x。根据不同的系统类型选择不同的安装包,从下图也可以看出 Consul 支持所有主流系统。

技术图片

 

 

 

 

1、安装consul

将下载的解压包保存在linux虚拟中,解压到指定目录中

#解压zip压缩包,到/usr/local/server/consul目录
unzip consul_1.5.3_linux_amd64.zip -d /usr/local/server/consul
##测试一下
./consul

 

2、启动consul服务

#进入目录/usr/local/server/consul 输入consul
./consul agent -dev -client=0.0.0.0
?
# -dev      参数表示开发
# -ui       参数表示打开ui,否则看不到ui界面。
# -node     参数表示给这个节点增加一个名称
# -client   参数表示绑定 ip 0.0.0.0,表示外部地址都可访问

 

技术图片

 

 

 

启动成功之后访问: http://192.168.126.99:8500/ui/dc1/services ,可以看到 Consul 的管理界面

技术图片

 

 

 

 

三、consul的基本使用

Consul 支持健康检查,并提供了 HTTP 和 DNS 调用的API接口完成服务注册,服务发现,以及K/V存储这些功能。接下来通过发送HTTP请求的形式来了解一下Consul

1、服务注册与发现

(1)注册服务

通过postman发送put请求到 http://192.168.126.99:8500/v1/catalog/register地址可以完成服务注册

{
    "Datacenter": "dc1",
    "Node": "node01",
    "Address": "192.168.74.102",
    "Service": {
        "ID":"mysql-01",
        "Service": "mysql",
        "tags": ["master","v1"],
        "Address": "192.168.74.102",
        "Port": 3306
        }
}

 



技术图片

技术图片

 

 

 

 

(2)服务查询

通过postman发送get请求到 http://192.168.126.99:8500/v1/catalog/services查看所有的服务列表

技术图片

 

 

 

通过postman发送get请求http://192.168.126.99:8500/v1/catalog/service/ +服务名 查看具体的服务详情

技术图片

 

 

 

(3)服务删除

通过postman发送put请求到http://192.168.126.99:8500/v1/catalog/deregister删除服务

{
    "Datacenter": "dc1",
    "Node": "node01",
    "ServiceID": "mysql-01"
}

 

 

技术图片

 

 

 

 

2、Consul的KV存储

可以参照Consul提供的KV存储的 API完成基于Consul的数据存储

含义请求路径请求方式
查看key v1/kv/:key GET
保存或更新 v1/kv/:key put
删除 /v1/kv/:key DELETE

 

  • key值中可以带/, 可以看做是不同的目录结构。

  • value的值经过了base64_encode,获取到数据后base64_decode才能获取到原始值。数据不能大于512Kb

  • 不同数据中心的kv存储系统是独立的,使用dc=?参数指定。

四、项目引入consul的服务注册

(1)案例准备


技术图片

 

 

 

 

(2)修改微服务的相关pom文件

修改商品、订单服务的pom文件,添加SpringCloud提供的基于Consul的依赖

 <!--SpringCloud提供的基于Consul的服务发现-->
<dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-consul-discovery</artifactId>
    </dependency>
<!--actuator用于心跳检查-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

 

其中 spring-cloud-starter-consul-discovery 是SpringCloud提供的对consul支持的相关依赖。 ? spring-boot-starter-actuator 适用于完成心跳检测响应的相关依赖。

 

(3)修改application配置文件

修改商品、订单服务的application.yml配置文件,添加consul服务发现的相关配置信息

###开始配置consul的服务注册
cloud:
  consul:
    host: 192.168.126.99 #consul服务器的主机地址
    port: 8500 #consul服务器的ip地址
    discovery:
      #是否需要注册
      register: true
      #注册的实例ID (唯一标志)
      instance-id: ${spring.application.name}-1
      #服务的名称
      service-name: ${spring.application.name}
      #服务的请求端口
      port: ${server.port}
      #指定开启ip地址注册
      prefer-ip-address: true
      #当前服务的请求ip
      ip-address: ${spring.cloud.client.ip-address}

 

其中 spring.cloud.consul 中添加consul的相关配置

  • host:表示Consul的Server的请求地址

  • port:表示Consul的Server的端口

  • discovery:服务注册与发现的相关配置

    • instance-id : 实例的唯一id(推荐必填),spring cloud官网文档的推荐,为了保证生成一个唯一的id ,也可以换成${spring.application.name}:${spring.cloud.client.ipAddress}

    • prefer-ip-address:开启ip地址注册

    • ip-address:当前微服务的请求ip

(4)修改订单服务主项目类

修改OrderApplication类,添加Ribbon负载均衡的注解;springcloud对consul进行了进一步的处理,向其中集成了ribbon的支持

###开始配置consul的服务注册
cloud:
  consul:
    host: 192.168.126.99 #consul服务器的主机地址
    port: 8500 #consul服务器的ip地址
    discovery:
      #是否需要注册
      register: true
      #注册的实例ID (唯一标志)
      instance-id: ${spring.application.name}-1
      #服务的名称
      service-name: ${spring.application.name}
      #服务的请求端口
      port: ${server.port}
      #指定开启ip地址注册
      prefer-ip-address: true
      #当前服务的请求ip
      ip-address: ${spring.cloud.client.ip-address}

 

 

(5)修改OrderController类,使用负载均衡策略调用。

@RestController
@RequestMapping("/order")
public class OrderController {//注入restTemplate对象
    @Autowired
    private RestTemplate restTemplate;
?
    @RequestMapping(value = "/buy/{id}",method = RequestMethod.GET)
    public Product findById(@PathVariable Long id) {
        //Ribbon负载均衡调用
        Product product = restTemplate.getForObject("http://service-product/product/"+id,Product.class);;
        //Product product = restTemplate.getForObject("http://localhost:9001/product/"+id,Product.class);
        return product;
    }
?
}

 

 

(6)在控制台中查看服务列表

技术图片

 

 

 

 

五、consul高可用集群

技术图片

 

 

 

此图是官网提供的一个事例系统图,图中的Server是consul服务端高可用集群,Client是consul客户端。consul客户端不保存数据,客户端将接收到的请求转发给响应的Server端。Server之间通过局域网或广域网通信实现数据一致性。每个Server或Client都是一个consul agent。Consul集群间使用了GOSSIP协议通信和raft一致性算法。上面这张图涉及到了很多术语:

  • Agent——agent是一直运行在Consul集群中每个成员上的守护进程。通过运行 consul agent来启动。 agent可以运行在client或者server模式。指定节点作为client或者server是非常简单的,除非有其他agent实例。所有的agent都能运行DNS或者HTTP接口,并负责运行时检查和保持服务同步。

  • Client——一个Client是一个转发所有RPC到server的代理。这个client是相对无状态的。client唯一执行的后台活动是加入LAN

  • gossip池。这有一个最低的资源开销并且仅消耗少量的网络带宽。

  • Server——一个server是一个有一组扩展功能的代理,这些功能包括参与Raft选举,维护集群状态,响应RPC查询,与其他数据中心交互WANgossip和转发查询给leader或者远程数据中心。

  • DataCenter——虽然数据中心的定义是显而易见的,但是有一些细微的细节必须考虑。例如,在EC2中,多个可用区域被认为组成一个数据中心?我们定义数据中心为一个私有的,低延迟和高带宽的一个网络环境。这不包括访问公共网络,但是对于我们而言,同一个EC2中的多个可用区域可以被认为是一个数据中心的一部分。

  • Consensus——在我们的文档中,我们使用Consensus来表明就leader选举和事务的顺序达成一致。由于这些事务都被应用到有限状态机上,Consensus暗示复制状态机的一致性。

  • Gossip——Consul建立在Serf的基础之上,它提供了一个用于多播目的的完整的gossip协议。 Serf提供成员关系,故障检测和事件广播。更多的信息在gossip文档中描述。这足以知道gossip使用基于UDP的随机的点到点通信。

  • LAN Gossip——它包含所有位于同一个局域网或者数据中心的所有节点。 WAN

  • Gossip——它只包含Server。这些server主要分布在不同的数据中心并且通常通过因特网或者广域网通信。

 

在每个数据中心,client和server是混合的。一般建议有3-5台server。这是基于有故障情况下的可用性和性能之间的权衡结果,因为越多的机器加入达成共识越慢。然而,并不限制client的数量,它们可以很容易的扩展到数千或者数万台。

同一个数据中心的所有节点都必须加入gossip协议。这意味着gossip协议包含一个给定数据中心的所有节点。这服务于几个目的:第一,不需要在client上配置server地址。发现都是自动完成的。第二,检测节点故障的工作不是放在server上,而是分布式的。这是的故障检测相比心跳机制有更高的可扩展性。第三:它用来作为一个消息层来通知事件,比如leader选举发生时。

每个数据中心的server都是Raft节点集合的一部分。这意味着它们一起工作并选出一个leader,一个有额外工作的server。leader负责处理所有的查询和事务。作为一致性协议的一部分,事务也必须被复制到所有其他的节点。因为这一要求,当一个非leader得server收到一个RPC请求时,它将请求转发给集群leader(与zookeeper一样)。

server节点也作为WAN gossip Pool的一部分。这个Pool不同于LAN Pool,因为它是为了优化互联网更高的延迟,并且它只包含其他Consul server节点。这个Pool的目的是为了允许数据中心能够以low-touch的方式发现彼此。这使得一个新的数据中心可以很容易的加入现存的WAN gossip。因为server都运行在这个pool中,它也支持跨数据中心请求。当一个server收到来自另一个数据中心的请求时,它随即转发给正确数据中想一个server。该server再转发给本地leader。

这使得数据中心之间只有一个很低的耦合,但是由于故障检测,连接缓存和复用,跨数据中心的请求都是相对快速和可靠的。

 

1、Consul的核心知识

Gossip协议

传统的监控,如ceilometer,由于每个节点都会向server报告状态,随着节点数量的增加server的压力随之增大。在所有的Agent之间(包括服务器模式和普通模式)运行着Gossip协议。服务器节点和普通Agent都会加入这个Gossip集群,收发Gossip消息。每隔一段时间,每个节点都会随机选择几个节点发送Gossip消息,其他节点会再次随机选择其他几个节点接力发送消息。这样一段时间过后,整个集群都能收到这条消息。示意图如下

技术图片

 

  

RAFT一致性算法

技术图片

 

 

 

为了实现集群中多个ConsulServer中的数据保持一致性,consul使用了基于强一致性的RAFT算法。在Raft中,任何时候一个服务器可以扮演下面角色之一:

  1. Leader: 处理所有客户端交互,日志复制等,一般一次只有一个Leader.

  2. Follower: 类似选民,完全被动

  3. Candidate(候选人): 可以被选为一个新的领导人。

 

Leader全权负责所有客户端的请求,以及将数据同步到Follower中(同一时刻系统中只存在一个Leader)。Follower被动响应请求RPC,从不主动发起请求RPC。Candidate由Follower向Leader转换的中间状态。 ? 关于RAFT一致性算法有一个经典的动画http://thesecretlivesofdata.com/raft/,其中详细介绍了选举,数据同步的步骤。

技术图片

 

 

 

2、Consul 集群搭建

技术图片

 

 

首先需要有一个正常的Consul集群,有Server,有Leader。这里在服务器Server1、Server2、Server3上分别部署了Consul Server。(这些服务器上最好只部署Consul程序,以尽量维护Consul Server的稳定)

服务器Server4和Server5上通过Consul Client分别注册Service A、B、C,这里每个微服务分别部署在了两个服务器上,这样可以避免Service的单点问题。(一般微服务和Client绑定)

在服务器Server6中Program D需要访问Service B,这时候Program D首先访问本机Consul Client提供的HTTP API,本机Client会将请求转发到Consul Server,Consul Server查询到Service B当前的信息返回

 

(1) 准备环境

服务器ipconsul类型Node(节点名称)序号
192.168.126.100 server server-1 s1
192.168.126.101 server server-2 s2
192.168.126.102 server server-3 s3
192.168.126.99 client client-1 s4

 

  • Agent 以 client 模式启动的节点。在该模式下,该节点会采集相关信息,通过 RPC 的方式向server 发送。Client模式节点有无数个,官方建议搭配微服务配置

  • Agent 以 server 模式启动的节点。一个数据中心中至少包含 1 个 server 节点。不过官方建议使用3 或 5 个 server 节点组建成集群,以保证高可用且不失效率。server 节点参与 Raft、维护会员信息、注册服务、健康检查等功能。

 

(2) 安装consul并启动

在每个consul节点上安装consul服务,下载安装过程和单节点一致。

##从官网下载最新版本的Consul服务
wget https://releases.hashicorp.com/consul/1.5.3/consul_1.5.3_linux_amd64.zip
##使用unzip命令解压到指定目录下 /usr/local/myserver/consul
unzip consul_1.6.3_linux_amd64.zip -d /usr/local/myserver/consul
##测试一下
./consul

 

启动每个consul server节点

##登录s1虚拟机,以server形式运行
./consul agent -server -bootstrap-expect 3 -data-dir /etc/consul.d -node=server-1 -bind=192.168.126.100 -ui -client 0.0.0.0 &
##登录s2 虚拟机,以server形式运行
./consul agent -server -bootstrap-expect 2 -data-dir /etc/consul.d -node=server-2 -bind=192.168.126.101 -ui -client 0.0.0.0 &
##登录s3 虚拟机,以server形式运行
./consul agent -server -bootstrap-expect 2 -data-dir /etc/consul.d -node=server-3 -bind=192.168.126.102 -ui -client 0.0.0.0 &

 

-server: 表示该 agent是一个 serverAgent,不添加这个选项则表示是一个 clientAgent

-bootstrap-expect:该命令通知 consul 准备加入集群的节点个数,集群要求的最少server数量,当低于这个数量,集群即失效。

-data-dir:表示相关数据存储的目录位置,在 serverAgent上该命令所指示的目录下会存储一些集群的状态信息

-node:节点id,在同一集群不能重复。 -bind:指定 agent 的 Ip。

-client:客户端的ip地址(0.0.0.0表示不限制),如不添加该指令,则 UI 只能在当前机器上访问

-join: 将该节点加入集群中

& :在后台运行,此为linux脚本语法

至此三个Consul Server模式服务全部启动成功。

启动s4,使用client形式启动consul

##登录s2 虚拟机中使用client形式启动consul
./consul agent -client=0.0.0.0 -data-dir /etc/consul.d -node=client-1 -bind=192.168.126.99 -ui &

 

(3) 每个节点加入集群

防火墙打开每个consul服务的相关端口

firewall-cmd --zone=public --add-port=8300/tcp --permanent
firewall-cmd --zone=public --add-port=8301/tcp --permanent
firewall-cmd --zone=public --add-port=8500/tcp --permanent
firewall-cmd --reload   #重启防火墙

 

以s1为leader,在s2,s3,s4 服务其上通过consul join 命令加入 s1中的consul集群中

##加入consul集群
./consul join 192.168.126.100

 

(4) 测试

在任意一台服务器中输入 consul members查看集群中的所有节点信息

##查看consul集群节点信息
./consul members

 

技术图片

 

 

 

访问 http://192.168.126.99:8500/ui/dc1/services

技术图片

 

 

技术图片

 

 

 

3、Consul 常见问题

(1)节点和服务注销

当服务或者节点失效,Consul不会对注册的信息进行剔除处理,仅仅标记已状态进行标记(并且不可使用)。如果担心失效节点和失效服务过多影响监控。可以通过调用HTTP API的形式进行处理

节点和服务的注销可以使用HTTP API:

  • 注销任意节点和服务:/catalog/deregister

  • 注销当前节点的服务:/agent/service/deregister/:service_id

     

如果某个节点不继续使用了,也可以在本机使用consul leave命令,或者在其它节点使用consul force-leave 节点Id。

(2)健康检查与故障转移

在集群环境下,健康检查是由服务注册到的Agent来处理的,那么如果这个Agent挂掉了,那么此节点的健康检查就处于无人管理的状态。

从实际应用看,节点上的服务可能既要被发现,又要发现别的服务,如果节点挂掉了,仅提供被发现的功能实际上服务还是不可用的。当然发现别的服务也可以不使用本机节点,可以通过访问一个nginx实现的若干Consul节点的负载均衡来实现。

 

 

 

 


感谢itheima提供的材料

以上是关于SpringCloud学习总结——服务注册中心Consul的主要内容,如果未能解决你的问题,请参考以下文章

SpringCloud 学习笔记总结

SpringCloud学习总结——服务注册中心Consul

SpringCloud开发学习总结—— 客户端负载均衡Ribbon

SpringCloud 学习笔记总结

全网最新springCloud快速练手学习项目——简单超易懂系列

SpringCloud学习笔记-p1(服务拆分&远程调用&Eureka注册中心&Ribbon负载均衡)