本文来自网易云社区
作者:乔安然
etcd是CoreOS开发的分布式高可用键值存储系统。随着CoreOS和K8s等项目在开源社区日益火热,etcd组件也渐渐为开发人员所关注。
etcd也是受到ZooKeeper与doozer启发而催生的项目,除了拥有类似功能,更专注于以下四点。
简单:基于HTTP+JSON的API让你用curl就可以轻松使用(V3版本不再使用JSON)。
安全:可选SSL客户认证机制。
快速:每个实例每秒支持一千次写操作。
可信:使用Raft算法充分实现了分布式。
在项目对比etcd和zookeeper之后,etcd更轻型容易部署安装使用,zk特性比较丰富,但已老态龙钟,需要点新鲜选择。在去年我党生日迎来了etcd v3(使用gRPC、改变key ttl使用租约等),蛋疼的发现java客户端etcd4j不支持v3版本,v2版本目前可以满足我们需求,继续使用etcd,后续会关注etcd4j更新。本文基于etcd v2版本使用。
etcd事件监听
etcd没有提供被动监听的实现,我们可以主动轮训监听key的变化。如果想监听其子节点可以通过recursive=true参数
“curl http://127.0.0.1:2379/v2/keys/foo?wait=true”
对/foo的改变会受到通知和返回相关变化事件
HTTP/1.1 200 OK
Content-Type: application/json
X-Etcd-Cluster-Id: e88d54f6225f06ad
X-Etcd-Index: 271
X-Raft-Index: 872202
X-Raft-Term: 5
Date: Sat, 26 Sep 2015 08:43:17 GMT
Transfer-Encoding: chunked
{
"action":
"set",
"node": {
"createdIndex": 7,
"key": "/foo",
"modifiedIndex": 7,
"value": "bar"},
"prevNode": {
"createdIndex": 6,
"key": "/foo",
"modifiedIndex": 6,
"value": "bar"}}
etcd中的数据变化(包括目录和key、value变化)相关类型事件:set、get、create、update、delete、expire、compareAndSwap、compareAndDelete。在返回的http response中的action属性就是事件类型,如上图所示。
etcd记录下最近1000次事件变化,使用index我们可以watch其key在过去发生的变化。使用node的modifiedIndex+1就可以监听下一次事件:
curl
'http://127.0.0.1:2379/v2/keys/foo?wait=true&waitIndex=8'
但当事件突发比如1秒内产生几千条事件,事件监听处理比较慢或者未监听是发生了客户端事件丢失。当我们index超过etcd记录的返回,就返回如下消息:
{
"errorCode"
:
401
,
"message"
:
"The event in requested index is outdated and cleared"
,
"cause"
:
"the requested history has been cleared [1008/8]"
,
"index"
:
2007
}
官方文档中推荐使用X-Etcd-Index+1作为waitIndex代替使用node的modifiedIndex+1:
1. X-Etcd-Index代表etcd当前index,为所有key共享。单挑递增总是大于或等于modifiedIndex,而这个modifiedIndex是etcd已经存储事件的index
2. modifiedIndex和X-Etcd-Index之间不代表有事件发生,当fetch 相关key不会有事件返回。
使用modifiedIndex+1只是功能表示后续监听,它比X-Etcd-Index+1小,很可能相关事件已经被清除,可能会受到401EventIndexCleared 错误。在初始监听或断开重新监听,index应该使用X-Etcd-Index+1,而不是modified