通過etcd v2 API的HTTP+JSON,很方便的用curl來調用etcd v2 API,有如下的內容:
- 集群管理API
一、集群管理API
1、查看版本
[root@localhost etcd-v3.3.10-linux-amd64]# curl -L http://127.0.0.1:2379/version {"etcdserver":"3.3.10","etcdcluster":"3.3.0"}
2、集群狀態
# 返回true則是健康的 [root@localhost etcd-v3.3.10-linux-amd64]# curl -L http://127.0.0.1:2379/health {"health":"true"}
3、leader數據
etcd的集群可以獲取整個集群的:
- 節點時延信息
- 失敗/成功的RPC請求次數
[root@localhost ~]# curl -L http://127.0.0.1:2379/v2/stats/leader { "leader": "57bf4d2527966724", "followers": { "4c14bc06668e9505": { "latency": { "current": 0.001479, "average": 0.003306272727272727, "standardDeviation": 0.0017684453414284075, "minimum": 0.000948, "maximum": 0.006036 }, "counts": { "fail": 0, "success": 11 } }, "a11e107c0081dbf8": { "latency": { "current": 0.001337, "average": 0.0033447999999999999, "standardDeviation": 0.0036313811091649415, "minimum": 0.00096, "maximum": 0.011139 }, "counts": { "fail": 0, "success": 10 } } } }
4、節點自身數據
[root@localhost ~]# curl -L http://127.0.0.1:2379/v2/stats/self { "name": "etcd2", "id": "57bf4d2527966724", "state": "StateLeader", "startTime": "2021-02-14T08:28:31.154812422+08:00", "leaderInfo": { "leader": "57bf4d2527966724", "uptime": "4h55m26.902989917s", "startTime": "2021-02-14T11:23:54.355889296+08:00" }, "recvAppendRequestCnt": 391, "sendAppendRequestCnt": 21 }
其中:
- name 該節點的name
- id 該節點的唯一標識
- state 該節點是否是leader
- startTime 該etcdServer啟動時間
- leaderInfo.leader 集群當前leader的id
- leaderInfo.uptime 集群當前leade的在任時長
- leaderInfo.startTime 集群當前leade的啟動時間
- recvAppendRequestCnt 該節點已處理的append請求數
- sendAppendRequestCnt 該節點已發送的append請求數
5、數據統計
etcd集群中全部節點都會記錄修改存儲的狀態,比如,增加、修改、刪除等狀態,通過以下API可以獲取其計數:
[root@localhost ~]# curl -L http://127.0.0.1:2379/v2/stats/store { "getsSuccess": 27, "getsFail": 33, "setsSuccess": 44, "setsFail": 0, "deleteSuccess": 1, "deleteFail": 0, "updateSuccess": 1, "updateFail": 0, "createSuccess": 6, "createFail": 1, "compareAndSwapSuccess": 0, "compareAndSwapFail": 0, "compareAndDeleteSuccess": 1, "compareAndDeleteFail": 0, "expireCount": 2, "watchers": 0 }
二、寫、讀、改、刪除
etcd v2的鍵一般位於路徑"v2/keys"路徑下,例如,message這個鍵的完整路徑是“/v2/keys/message”,那么如何通過API的形式實現呢?
1、寫
[root@localhost etcd-v3.3.10-linux-amd64]# curl -L http://127.0.0.1:2379/v2/keys/message -XPUT -d value="hello" {
"action":"set",
"node":{
"key":"/message",
"value":"hello",
"modifiedIndex":19,
"createdIndex":19
}
}
在返回的json數據中,其中action表示請求的動作是set。在v2 API中創建鍵值或者更新鍵值使用的都是PUT方法。 在node中,node.key是需要設置的鍵;node.value是需要設置的值;對etcd來說,每次創建一個鍵值都會產生一個唯一的createdIndex,第一個key的createdIndex是2而非1;任何更改行為(create、delete、set)都會更該modifiedIndex的值。
2、讀
[root@localhost ~]# curl -L http://127.0.0.1:2379/v2/keys/message { "action": "get", "node": { "key": "/message", "value": "hello", "modifiedIndex": 19, "createdIndex": 19 } }
3、改
[root@localhost ~]# curl -L http://127.0.0.1:2379/v2/keys/message -XPUT -d value="message1" { "action": "set", "node": { "key": "/message", "value": "message1", "modifiedIndex": 23, "createdIndex": 23 }, "prevNode": { "key": "/message", "value": "hello", "modifiedIndex": 19, "createdIndex": 19 } }
可以看到更改之前的key會多返回一個字段prevNode信息,這是之前存儲的key信息。
4、刪除
{ "action": "delete", "node": { "key": "/message", "modifiedIndex": 24, "createdIndex": 23 }, "prevNode": { "key": "/message", "value": "message1", "modifiedIndex": 23, "createdIndex": 23 } }
刪除鍵值,它會將之前修改過的記錄全部返回。
三、TTL
etcd的鍵可以通過TTL設置過期時間,一旦過了設置的時間,鍵就會被自動刪掉。
[root@localhost ~]# curl -L http://127.0.0.1:2379/v2/keys/message1 -XPUT -d value="hello" -d ttl=20 { "action": "set", "node": { "key": "/message1", "value": "hello", "expiration": "2021-02-14T02:12:27.005370199Z", "ttl": 20, "modifiedIndex": 25, "createdIndex": 25 } }
上述的返回值中node.expiration表示在該時刻這個鍵會過期,ttl表示還有多少秒會過期,一旦到期會自動刪除該鍵。如下:
[root@localhost ~]# curl -L http://127.0.0.1:2379/v2/keys/message1 { "errorCode": 100, "message": "Key not found", "cause": "/message1", "index": 26 }
當然你可以接着刷新ttl:
[root@localhost ~]# curl -L http://127.0.0.1:2379/v2/keys/message1 -XPUT -d value="hello" -d ttl=20 -d prevExit=true { "action": "set", "node": { "key": "/message1", "value": "hello", "expiration": "2021-02-14T02:18:48.300233144Z", "ttl": 20, "modifiedIndex": 28, "createdIndex": 28 }, "prevNode": { "key": "/message1", "value": "hello", "expiration": "2021-02-14T02:18:29.321723784Z", "ttl": 2, "modifiedIndex": 27, "createdIndex": 27 } }
四、觀察者(watch)
watch是觀察一個key並且等待接收消息,它有以下內容:
- watch一個key
- 帶索引的watch
- stream watch
1、watch一個key
在一個終端中發起一個get請求,並且設置參數wait=true:
[root@localhost ~]# curl -L http://127.0.0.1:2379/v2/keys/message1?wait=true
此時,會一直阻塞在這里。
接着,再另起一個終端,進行key的更新:
[root@localhost ~]# curl -L http://127.0.0.1:2379/v2/keys/message1 -XPUT -d value="hello1" { "action": "set", "node": { "key": "/message1", "value": "hello1", "modifiedIndex": 30, "createdIndex": 30 } }
在第一個終端中就能觀察這個key的變化:
[root@localhost ~]# curl -L http://127.0.0.1:2379/v2/keys/message1?wait=true { "action": "set", "node": { "key": "/message1", "value": "hello1", "modifiedIndex": 30, "createdIndex": 30 } }
一旦監聽到key的變化就會退出,這就是“一次性watch”。
2、帶索引的watch
帶索引的watch可以觀察到歷史記錄,保證信息的不丟失,上述的watch只是watch當前及以后的發生事件。其步驟如下:
- 獲取key當前的狀態
- 從key當前的modiifiedIndex+1開始watch
獲取key當前狀態:
[root@localhost ~]# curl -i http://127.0.0.1:2379/v2/keys/message1 HTTP/1.1 200 OK Content-Type: application/json X-Etcd-Cluster-Id: 735c420e06827765 X-Etcd-Index: 30 X-Raft-Index: 216 X-Raft-Term: 59 Date: Sun, 14 Feb 2021 02:51:36 GMT Content-Length: 98 { "action": "get", "node": { "key": "/message1", "value": "hello1", "modifiedIndex": 30, "createdIndex": 30 } }
此時可以從31及以后的位置開始watch,比如33:
[root@localhost ~]# curl -L http://127.0.0.1:2379/v2/keys/message1?wait=true &waitIndex=33
此時,只要等到這個key的modifiedIndex的值等於33是才會有響應。
3、stream watch
也被稱為持久化watch,也就是客戶端保持長鏈接,中途不會因為監控到變化有返回值而中斷鏈接。只需要在請求參數中添加stream=true即可:
[root@localhost ~]# curl http://127.0.0.1:2379/v2/keys/message1?wait=true&stream=true
stream watch即使收到事件也不會退出;“一次性watch”只要收到事件就會退出,然后再重新發起watch。不過stream watch它是持續watch當前及以后的事件,歷史事件也是無能為力。
五、原子操作
原子操作包括:
- CAS
- CAD
1、CAS(Compare And Swap)
先比較客戶端與所提供的條件是否一樣,如果不一樣就進行交換,CAS的比較條件包括:
- prevValue 檢查key之前的value
- prevIndex 檢查key之前的modifiedIndex
- prevExist 檢查key是否存在,如果存在是一個更新操作,如果不存在是一個新建操作
新建一個鍵值對:
[root@localhost ~]# curl -L http://127.0.0.1:2379/v2/keys/msg -XPUT -d value="val" { "action": "set", "node": { "key": "/msg", "value": "val", "modifiedIndex": 53, "createdIndex": 53 } }
prevExist的使用:
[root@localhost ~]# curl -L http://127.0.0.1:2379/v2/keys/msg?prevExist=false -XPUT -d value="val1" { "errorCode": 105, "message": "Key already exists", "cause": "/msg", "index": 53 }
顯然這個key已經存在了,現在參數是false,所以會報錯。正確的是參數傳遞true:
[root@localhost ~]# curl -L http://127.0.0.1:2379/v2/keys/msg?prevExist=true -XPUT -d value="val1" { "action": "update", "node": { "key": "/msg", "value": "val1", "modifiedIndex": 54, "createdIndex": 53 }, "prevNode": { "key": "/msg", "value": "val", "modifiedIndex": 53, "createdIndex": 53 } }
prevValue與prevIndex的用法相似。
2、CAD(Compare And Delete)
先比較客戶端與所提供的條件是否一樣,如果一樣就刪除對應的key,CAD的比較條件包括:
- prevValue 檢查key之前的value
- prevIndex 檢查key之前的modifiedIndex
使用之前的msg鍵值:
[root@localhost ~]# curl -L http://127.0.0.1:2379/v2/keys/msg?prevValue=val1 -XDELETE { "action": "compareAndDelete", "node": { "key": "/msg", "modifiedIndex": 55, "createdIndex": 53 }, "prevNode": { "key": "/msg", "value": "val1", "modifiedIndex": 54, "createdIndex": 53 } }
prevIndex用法與之類似。