集群管理工具consul学习笔记

-目录-

Consul功能与原理

功能原理

consul是一个集群管理工具,特点:

解决了手动配置服务的痛点。

每个consul agent(节点)有3种模式:

工作流程:每个agent都可以注册一些RPC或者说是服务,从网络传给server类型的agent一些RPC,这些RPC会根据服务列表直接访问服务层或者分发给其他Client,那些client再调用服务层。其中LeaderServer由其他server投票选出,通过轮询记录其他agent的地址与注册在agent的服务,这也即服务列表,当然会同步给其他server。当Leader下线后,会触发重新投票选出LeaderServer。

img

端口功能:

一致性算法-Gossip协议

算法详解

朴素原理:Gossip协议是基于六度分隔理论(Six Degrees of Separation)哲学的体现,简单的来说,一个人通过6个中间人可以认识世界任何人。这意味着不需要很多次信息交换,就可以蔓延到整个网络。

Gossip协议在计算机系统通常以随机的“对等选择”形式实现:以给定的频率,每台计算机随机选择另一台计算机,并共享任何消息。定义十分简单,所以实现方式非常多。

一种原始的Gossip协议的执行过程:

Gossip 协议的消息传播方式有两种:Anti-Entropy(反熵传播)和Rumor-Mongering(谣言传播),反熵传播使用“simple epidemics(SI model)”的方式:以固定的概率传播所有的数据。所有参与节点只有两种状态:

Suspective(病原):处于 susceptible 状态的节点代表其并没有收到来自其他节点的更新。
Infective(感染):处于 infective 状态的节点代表其有数据更新,并且会将这个数据分享给其他节点。

​ 反熵传播过程是每个节点周期性地随机选择其他节点,然后通过互相交换自己的所有数据来消除两者之间的差异。反熵传播方法每次节点两两交换自己的所有数据会带来非常大的通信负担,因此不会频繁使用,通常只用于新加入节点的数据初始化。

谣言传播使用“complex epidemics”(SIR model)的方式:以固定的概率仅传播新到达的数据。所有参与节点有三种状态:Suspective(病原)、Infective(感染)、Removed(愈除)。

Removed(愈除):其已经接收到来自其他节点的更新,但是其并不会将这个更新分享给其他节点。

​ 谣言传播过程是消息只包含最新 update,谣言消息在某个时间点之后会被标记为removed,并且不再被传播。缺点是系统有一定的概率会不一致,通常用于节点间数据增量同步。

​ 一般来说,为了在通信代价和可靠性之间取得折中,需要将这两种方法结合使用。

Gossip的优势与缺点:

缺点:

Consul操作

创建服务端

consul agent -server -bootstrap-expect 3 -data-dir /tmp/consul -bind=192.168.0.104 -client 0.0.0.0 -node=s_hallen -rejoin -ui -join 192.168.0.104

更多参数说明

参数说明:

挂载服务

将服务挂载到agent,可以在启动agent时使用-config-dir指定配置文件,文件内加上service字段,在其中写上挂载服务的信息。当服务挂载到agent并启动时,agent会自动检测该服务的健康状态(需要配置checks字段)。

{
  "service":{
    "id": "consul-service-demo",
    "name": "consul-service-demo",
    "address": "127.0.0.1",
    "port": 8080,
    "tags": ["uth","report"],
    "checks":[
      {
        "http": "http://127.0.01:8080/health",
        "interval": "10s"
      }
    ]
  }
}

参数说明与其他参数

id:节点id

name:节点name

address:节点IP

port:节点端口

tags:节点标签,是个列表

checks:服务检查,列表,否则逻辑层下线后检测不到
    1.Script+ Interval
        {
            "id": "mem-util",
            "name": "Memoryutilization",
            "script": "/usr/local/bin/check_mem",    // 必须是shell脚本
            "interval": "10s",
            "timeout": "15s"    // 默认是30s
          }
    2.HTTP+ Interval
        请求超时时间等于调用请求的间隔时间
        {
            "id": "api",
            "name": "HTTPAPI on port 5000",
            "http": "http://localhost:5000/health",
            "interval": "10s",
            "timeout": "15s"
        }
	常用
    3.TCP+ Interval
        {
          "check": {
            "id": "ssh",
            "name": "SSHTCP on port 22",
            "tcp": "localhost:22",
            "interval": "10s",
            "timeout": "1s"
          }
        }

interval:每隔多长时间检测一次

datacenter:同命令行参数-datacenter

data_dir:同命令行参数-data_dir

bootstrap:同命令行参数-bootstrap

bootstrap_expect:同命令行参数-bootstrap_expect

bind_addr:同命令行参数-bind

enable_syslog:同命令行参数-syslog

log_level:同命令行参数-log_level

node_name:同命令行参数node

server:是否是server节点

服务发现

调用方获取相应服务地址的过程就是服务发现。一个service可以只挂载到一个agent上,当然这样就体现不出来微服务的容错性,可以同一个service挂载到多个agent上这样就可以实现容错性(注意虽然节点不同,但是服务名字相同)。那么调用端要选择哪个agent进行调用呢?这个问题留给调用端来解决。

方案1:在调用端内将agentIP地址写死,if-else不断尝试连接,这样理论上可行,但是实际上没人用,因为这样是硬编码,如果需要新增agent会改代码,亦或者单纯的agent够多(几千个client是常见的事情)代码会很难看。这种方法忽略了consul自带的重要的功能:服务发现。

方案2:使用consul自带的功能:服务发现。抛弃了硬编码形式。有几种方式可以获得在consul注册的服务

  1. http api形式,直接从consul里获取到服务(健康的或者不健康的)。调用api直接获得列表

    config := api.DefaultConfig()
    // 任意agent地址
    config.Address = "127.0.0.1:8500"
    
    //waitIndex是blocking query的实现机制,是watch机制的核心,只有改变了才返回
    var waitIndex uint64
    client_api,_ := api.NewClient(config)
    
    // 获取健康的服务,名称为“my_say_hi”
    services,_,_ := client_api.Health().Service("my_say_hi","say_hi",true,&api.QueryOptions{
        WaitIndex:waitIndex,
    })
    
    //选择一个,获取其服务地址
    address := services[0].Service.Address
    port := services[0].Service.Port
    url := fmt.Sprintf("%s:%d",address,port)
    
    //连接与调用
    conn,err := grpc.Dial(url,grpc.WithInsecure())
    
© 2019 - 2023 · YuYoung's Blog