Github地址:https://github.com/hashicorp/consul
版本:1.20.1(2024.10.29)
consul的session不会自动续期(etcd和zookeeper会自动续期,只要客户端没有断开连接,就一直有效),需要手动调用renew方法。
session过期的时候会将所有关联的键值对都移除
下载&运行
下载后只有一个consul.exe,用cmd运行
consul.exe agent -dev
默认启动在8500端口上(可以在浏览器中通过localhost:8500进入可视化页面)
配置
默认端口
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内使用
关于分布式锁在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