Administrator
Administrator
Published on 2024-12-18 / 22 Visits
0
0

consul

Github地址:https://github.com/hashicorp/consul

官网:https://consul.io/

版本:1.20.1(2024.10.29)

consul的session不会自动续期(etcd和zookeeper会自动续期,只要客户端没有断开连接,就一直有效),需要手动调用renew方法。

session过期的时候会将所有关联的键值对都移除

下载&运行

下载后只有一个consul.exe,用cmd运行

consul.exe agent -dev

默认启动在8500端口上(可以在浏览器中通过localhost:8500进入可视化页面)

配置

默认端口

服务

默认端口

描述

HTTP API

8500

Consul 的 HTTP 接口(主要用于用户访问和 API 调用)。

gRPC API

8502

Consul 的 gRPC 接口(可选)。

DNS 服务

8600

Consul 提供的内置 DNS 解析服务。

Serf LAN

8301

服务节点间的内部通信(TCP 和 UDP)。

Serf WAN

8302

集群跨数据中心的通信(TCP 和 UDP)。

Server RPC

8300

Consul 服务端之间的通信。

json配置文件

{
    "node_name": "consul-server-1", //默认使用计算机名
    "data_dir": "./data", //数据存放目录
    "server": true, //当前节点是否为consul服务端
    "bootstrap_expect": 3, //定义预期的服务器节点数量,用于自动选举 leader。
    "bind_addr": "192.168.1.100", //设置 Consul 服务绑定的 IP 地址。
    "advertise_addr": "",
    "client_addr": "0.0.0.0",
    "ports": {
      "http": 9500,
      "dns": 9600,
      "serf_lan": 9301,
      "serf_wan": 9302,
      "server": 9300
    },
    "retry_join": ["192.168.1.101", "192.168.1.102"],
    "acl": {
      "enabled": true,
      "default_policy": "deny",
      "tokens": {
        "master": "my-master-token"
      }
    },
    "log_level": "info",
    "ui": true,
    "services": [
      {
        "name": "web",
        "port": 80,
        "check": {
          "http": "http://localhost:80/health",
          "interval": "10s"
        }
      }
    ]
  }

用配置文件启动

consul.exe agent -config-file=conf.json

node.js内使用

npm模块页面

关于分布式锁在lock_op函数中。kv_op中演示key/value用法,sess_op演示session的创建、续期、释放等

const Consul = require('consul')

var consul = new Consul({
    host: '', //(String, default: 127.0.0.1): agent address
    port: 8500, //(Integer, default: 8500): agent HTTP(S) port
    secure: false, //(Boolean, default: false): enable HTTPS
})


async function kv_op(){ //kv键值对操作
    var a = await consul.kv.set("test-1", "value-2") //新增或设置键的值
    console.log(a); //true
    

    // var b = await consul.kv.get("test-1") //获取某个键的值
    // console.log(b); //["test-1"]


    // var c = await consul.kv.keys() //获取所有键
    // var c = await consul.kv.keys("te") //获取te开头的键
    // console.log(c); //["test-1"]


    var d = await consul.kv.del("test-1") //删除一个键
    console.log(d); //true
}
// kv_op();


async function sess_op(){ //session操作
    var a = await consul.session.create({
        ttl: '10s', // 有效期。(String, optional, valid: 10s-86400s): interval session must be renewed
        behavior: 'delete', // Session将要过期时键值对是释放还是删除。(String, enum: release, delete; default: release): controls the behavior when a session is invalidated
        name: 'lock-name',
        lockdelay: '1s' //延迟释放。(String, range: 1s-60s, default: 15s): the time consul prevents locks held by the session from being acquired after a session has been invalidated
    })
    console.log(a); //{ ID: 'b4d67591-4def-f2ba-6db1-785bdd3422cd' }


    var b = await consul.session.info(a.ID) //这二个方法都是获取session信息
    console.log(b);
    var b = await consul.session.get(a.ID)
    console.log(b);


    var c = await consul.session.renew(a.ID) //session续期
    console.log(c); //true


    var d = await consul.session.destroy(a.ID) //释放,返回boolean
    console.log(d);
}
// sess_op()



async function lock_op(){
     //实测效果,不执行释放锁操作的情况下,session.create中的Option关联的锁,会在20秒后释放,而不是10s+1s=11秒释放。

    for(let i = 0; i<5; i++) {
        setTimeout(async () => {
            var joinTime = Date.now()
            var sess = await consul.session.create({
                ttl: '10s', // 有效期。(String, optional, valid: 10s-86400s): interval session must be renewed
                behavior: 'delete', // 将要移除Session时是释放还是删除。(String, enum: release, delete; default: release): controls the behavior when a session is invalidated
                name: 'lock-name',
                lockdelay: '1s' //延迟释放。(String, range: 1s-60s, default: 15s): the time consul prevents locks held by the session from being acquired after a session has been invalidated
            })
        
            var lock = await consul.kv.set({
                key: 'user1-lock',
                value: 'lock', //值随意
                acquire: sess.ID
            }) //Boolean。不成功时返回undefined,成功返回true
            

            if(!lock) {
                console.log(i, 'A组lock失败', lock, joinTime);
                return
            }
            console.log(i, 'A组lock成功', lock, joinTime);

            await new Promise(resolve => setTimeout(resolve, 1000));

            var release = await consul.kv.set({
                key: 'user1-lock',
                value: 'lock', //值随意
                release: sess.ID
            }) //Boolean。不成功时返回undefined,成功返回true
            console.log(i, 'release', release);
            
        }, 500);
    }
    


    setInterval(async () => {
        var joinTime = Date.now()
        var sess = await consul.session.create({
            ttl: '10s', // 有效期。(String, optional, valid: 10s-86400s): interval session must be renewed
            behavior: 'delete', 
            // (String, enum: release, delete; default: release): controls the behavior when a session         is invalidated
            // release:在session到期后将与session绑定的kv解绑,但依然存在
            // delete:到期后移除关联的kv

            name: 'lock-name',
            lockdelay: '1s' //延迟释放。(String, range: 1s-60s, default: 15s): the time consul prevents locks held by the session from being acquired after a session has been invalidated
        })
    
        var lock = await consul.kv.set({
            key: 'user1-lock',
            value: 'lock', //值随意
            acquire: sess.ID
        }) //Boolean。不成功时返回undefined,成功返回true
        

        if(!lock) {
            console.log('B组lock失败', lock, joinTime);
            return
        }
        console.log('B组lock成功', lock, joinTime);

        // await new Promise(resolve => setTimeout(resolve, 2000));

        // var release = await consul.kv.set({
        //     key: 'user1-lock',
        //     value: 'lock', //值随意
        //     release: sess.ID
        // }) //Boolean。不成功时返回undefined,成功返回true
        // console.log(i, 'release', release);
        
    }, 2000);
}
lock_op()

上面的代码执行日志:

0 A组lock成功 true 1734519701053
1 A组lock失败 undefined 1734519701059
3 A组lock失败 undefined 1734519701060
2 A组lock失败 undefined 1734519701059
4 A组lock失败 undefined 1734519701060
0 release true
B组lock成功 true 1734519702553
B组lock失败 undefined 1734519704553


Comment