Botposter.com集羣ETCD2.3.7升級至3.0實錄

7月1日,爲慶祝我黨生日,ETCD隆重發布了3.0版本。Botposter.com也在第一時間對集羣進行了升級。本文是升級過程的記錄與總結(文中假設讀者已經使用或測試過ETCD V2,若有不妥請見諒)。node

Botposet.com是一款與HubSpot相似的營銷自動化SAAS產品,所有使用golang開發。git

說明

在Botposter.com中,ETCD主要用於如下兩個職責:github

  • master選舉
  • 集羣信息保存

早期曾使用ETCD的TTL來實現master心跳檢測,因爲性能緣由在Botposter.com上個月的重構中取消了這種用法。這也剛好簡化了升級難度,由於ETCD v3對TTL有重大改動。golang

準備

資料準備

遷移工做的主要參考如下兩篇資料:服務器

https://github.com/coreos/etcd/blob/master/Documentation/op-guide/v2-migration.md架構

https://github.com/coreos/etcd/blob/master/Documentation/upgrades/upgrade_3_0.mdmvc

測試環境

開始升級前須要搭建測試環境,過程很是簡單,這一點ETCD作得很是好,V3版本與V2版本不管從安裝方式和配置參數徹底一致。tcp

安裝參考連接:https://github.com/coreos/etcd/releases分佈式

配置參考連接:https://github.com/coreos/etcd/blob/master/Documentation/op-guide/clustering.mdide

配置好測試環境後,使用etcdctl測試ETCD V3是否能夠正常使用。這裏須要注意,必定不要忘記在環境變量中加入ETCDCTL_API=3。不然在操做V3時,不管使用SET,GET都沒有任何數據返回,也沒有錯誤返回。建議ETCD V3能夠提供錯誤提示。我在這裏耽誤了一些時間,由於想固然的覺得,使用ETCD V3和ETCDCTL V3是默認匹配的。 ETCDCTL的文檔連接:https://github.com/coreos/etcd/blob/master/etcdctl/README.md#migrate-options

注意:我在第一次使用etcdctl member list命令(全部的命令都會出錯,此處以member list舉例)的時候,返回下面錯誤代碼:

grpc: addrConn.resetTransport failed to create client transport: connection error: desc = "transport: dial tcp 127.0.0.1:22379: getsockopt: connection refused"; Reconnecting to {"127.0.0.1:22379" <nil>}

單獨運行etcdctl命令,會返回etcdctl的使用幫助,其中有一行:

--endpoints=[127.0.0.1:2379,127.0.0.1:22379,127.0.0.1:32379]	gRPC endpoints

原來默認gRPC的endpoints有三個,解決這個問題的已知辦法有兩個: 一是在etcdctl命令行中加入--endpoints參數

etcdctl --endpoints=127.0.0.1:2379 member list

二是在etcd啓動參數中增長其它端口

-listen-client-urls http://127.0.0.1:2379,http://127.0.0.1:22379,http://127.0.0.1:32379

在Botposter.com中暫時使用第二種方法。由於遷移時間有限,沒有繼續查看是否能夠修改gRPC的默認--endpoints。

API V2與V3區別

  • 事務:ETCD V3提供了多鍵條件事務(multi-key conditional transactions),應用各類須要使用事務代替原來的Compare-And-Swap操做。
  • 平鍵空間(Flat key space):ETCD V3再也不使用目錄結構,只保留鍵。例如:"/a/b/c/"是一個鍵,而不是目錄。V3中提供了前綴查詢,來獲取符合前綴條件的全部鍵值,這變向實現了V2中查詢一個目錄下全部子目錄和節點的功能。
  • 簡潔的響應:像DELETE這類操做成功後將再也不返回操做前的值。若是但願得到刪除前的值,可使用事務,來實現一個原子操做,先獲取鍵值,而後再刪除。
  • 租約:租約代替了V2中的TTL實現,TTL綁定到一個租約上,鍵再附加到這個租約上。當TTL過時時,租約將被銷燬,同時附加到這個租約上的鍵也被刪除。

與Botposter.com有關的改動只有平鍵空間,由於系統中使用ETCD目錄結構保存了master,node和task的所有信息。 從官方文檔的表述看,事務和租約值得測試並用於優化V2的用法。

客戶端代碼升級

平鍵空間

將原代碼中包含如下代碼的部分都修改成

&client.GetOptions{Recursive: true}

都修改成

clientv3.WithPrefix()

數據類型

在V2版本中,resp.Node.ModifiedIndex的數據類型爲uint64,V3中revision爲int64。 由於在Botposter.com使用了resp.Node.ModifiedIndex做爲全局序列標識,因此,須要將原系統中的數據類型修改成int64。

Compare-And-Swap

在V2的一種典型用法就是Compare-And-Swap,在Botposter.com中也使用這種方法實現了分佈式鎖,實現方法是在SET操做時增長下面的操做:

&client.SetOptions{PrevExist: "false"})

即,只有當前key不存在時,才能寫入成功。

在V3中,改成由事務實現。具體代碼以下:

kvc := clientv3.NewKV(&cli)
r, _ := kvc.Txn(context.Background()).
	If(clientv3.Compare(clientv3.CreateRevision(key), "=", 0)).
	Then(clientv3.OpPut(key, v)).
	Commit()

Txn的具體用法參考:https://godoc.org/github.com/coreos/etcd/clientv3#example-KV--Txn

Node

在V2中,get操做response回來的value保存在response.node.value,若是是一個directory,返回的結果集保存在response.node.nodes中。 V3作了大幅修改,由於V3中再也不有directory,全部的key都是flat key,因此,全部get操做的返回值都保存在GetResponse.Kvs(數據類型是[]*mvccpb.KeyValue)中。並且V2中,keynotfound等錯誤在V3中都再也不保留,V3中,當查詢的key不存在時,GetResponse.Count爲0,len(GetResponse.Kvs)也爲0,Get操做返回的error爲nil。 因此在V2中的代碼如

response.Node.Value

須要改成

GetResponse.Kvs[0].Value

另外值得注意的是,V3中的key和value的返回值都是[]byte類型,這能夠減小不少string與[]byte的數據類型轉換操做。

ETCD升級

ETCD升級很簡單,先按照安裝參考連接:https://github.com/coreos/etcd/releases ,下載並解壓文件。 由於Bostposter.com集羣有自動恢復機制,因此使用離線升級的方式,在全部服務器運行腳本:

service etcd stop
cp etcd /usr/local/bin
service etcd start

ETCD的全部啓動參數都不須要修改,升級時間不超過1秒。 ETCD升級後,升級集羣服務的代碼,只有在升級流程容器時須要重啓2000多個流程,所有恢復時間大概在1分鐘左右。

至此,升級工做所有完成。對系統功能和集羣都作了測試,沒有出現任何問題。

感覺

下面說說升級到ETCD V3後的感覺,時間有限沒有作精確測試,沒有數據支撐略顯不夠嚴謹。

首先,V3服務器端的內存比V2佔用得更高,至少高50%。尤爲是壓力增大時,內存佔用飆升得很快,壓力減少後幾分鐘內存會釋放出來。

其次,Client使用後必定要Close,由於在V2時,Botposter.com中使用了sync.pool來保存Client。當升級到V3後,操做頻繁時池化的Client會佔用很是多的內存,由於沒有作具體測試,還不清楚一個Client佔用多少內存。目前的解決辦法是Client再也不池化,並且使用後當即Close。

第三,V3的API更加合理,直接的結果是代碼量減小了,異常處理也變得更簡單。

第四,從升級後的總體表現看,V3的性能比V2要不少。

總體來講,在有條件的狀況下,我建議升級至ETCD V3。時間倉促,若有筆誤請你們及時指出,謝謝。

內容爲做者原創,未經容許請勿轉載,謝謝合做。


關於做者: Jesse,目前在Joygenio工做,從事golang語言開發與架構設計。 正在開發維護的產品:www.botposter.com

相關文章
相關標籤/搜索