etcd watch:etcd 如何实现 watch 机制?
etcd watch:etcd 如何实现 watch 机制?
你好,我是 aoho,今天我和你分享的主题是 etcd watch:etcd 如何实现 watch 机制?
etcd v2 和 v3 版本之间的重要变化之一就是 watch 机制的优化。etcd v2 watch 机制采用的是基于 HTTP/1.x 协议的客户端轮询机制,历史版本存储则是通过滑动窗口。在大量的客户端连接的场景或者集群规模较大的场景,导致 etcd 服务端的扩展性和稳定性都无法保证。etcd v3 在此基础上进行优化,满足了 Kubernetes pods 部署和状态管理等业务场景诉求。
watch 是监听一个或一组 key,key 的任何变化都会发出消息。某种意义上讲,etcd 就是发布订阅模式。
Watch 的用法
在具体将讲解 Watch 的实现方式之前,我们先来体验下如何使用 Watch。通过 etcdctl 命令行工具实现键值对的检测:
$ etcdctl put hello aoho
$ etcdctl put hello boho
$ etcdctl watch hello -w=json --rev=1
{
"Header": {
"cluster_id": 14841639068965178418,
"member_id": 10276657743932975437,
"revision": 4,
"raft_term": 4
},
"Events": [{
"kv": {
"key": "aGVsbG8=",
"create_revision": 3,
"mod_revision": 3,
"version": 1,
"value": "YW9obw=="
}
}, {
"kv": {
"key": "aGVsbG8=",
"create_revision": 3,
"mod_revision": 4,
"version": 2,
"value": "Ym9obw=="
}
}],
"CompactRevision": 0,
"Canceled": false,
"Created": false
}
依次在命令行中输入上面三条命令,前面两条依次更新 hello 对应的值,第三条命令监测键为 hello 的变化,并指定版本号从 1 开始。结果输出了两条 watch 事件。我们接着在另一个命令行继续输入如下的更新命令:
$ etcdctl put hello coho
可以看到前一个命令行输出了如下的内容:
{
"Header": {
"cluster_id": 14841639068965178418,
"member_id": 10276657743932975437,
"revision": 5,
"raft_term": 4
},
"Events": [{
"kv": {
"key": "aGVsbG8=",
"create_revision": 3,
"mod_revision": 5,
"version": 3,
"value": "Y29obw=="
}
}],
"CompactRevision": 0,
"Canceled": false,
"Created": false
}
命令行输出的事件表明,键 hello
对应的键值对发生了更新,并输出了事件的详细信息。如上就是通过 etcdctl 客户端工具实现 watch 指定的键值对功能。接着我们看下,clientv3 中是如何实现 watch 功能。
func testWatch() {
s := newWatchableStore()
w := s.NewWatchStream()
w.Watch(start_key: foo, end_key: nil)
w.Watch(start_key: bar, end_key: nil)
for {
consume := <- w.Chan()
}
}
etcd 的 mvcc 模块对外提供了两种访问键值对的实现,一种是键值存储 kvstore,另一种是 watchableStore。它们都实现了 KV 接口,KV 接口的具体实现则是 store 结构体。在上面的实现中,我们先调用了 watchableStore。
当我们要使用 Watch 功能时,我们创建了一个 watchStream。创建出来的 w 可以监听的键为 hello,之后我们就可以消费 w.Chan()
返回的 channel。键为 hello 的任何变化,都会通过这个 channel 发送给客户端。
可以看到 watchStream 实现了在大量 kv 的变化中,过滤出当前所监听的 key,将 key 的变化输出。
- 点赞
- 收藏
- 关注作者
评论(0)