- 原文地址:Java and etcd: together at last, with jetcd
- 原文作者:Fanmin Shi
- 譯文出自:掘金翻譯計劃
- 本文永久連結:github.com/xitu/gold-m…
- 譯者:mingxing
- 校對者:xiantang
可靠的鍵值儲存為分散式系統提供了一致性配置和協調的公共基礎。etcd 專案就是一個這樣的系統,這是一個由 CoreOS 建立的開源鍵值儲存系統。它是許多生產級分散式系統的核心元件和 Kubernetes 等專案的資料儲存中心。
Java 已經通過在包括 Hadoop 生態系統、Cassandra 資料儲存和雲基礎設施技術棧中的使用而證明了自己是一種流行的分散式系統語言。此外,它仍然是一種非常流行的語言。可以看看在谷歌趨勢的統計資料中,Java 仍然佔據主導地位:
就谷歌搜尋結果而言,Java 仍然比 Microsoft 的 .Net 甚至 JavaScript 語言更受歡迎
面對著 Java 的流行及其在分散式系統中的普遍使用,我們認為對於 Java 開發來說,etcd 也應該作為後端基礎被使用到。jetcd 這個新的 etcd 客戶端的出現,將 etcd v3 API 帶到了 Java 中。
通過使用 jetcd,Java 應用程式可以使用包裝了 etcd 的原生 gRPC 協議的智慧 API 來與 etcd 進行純粹的互動。該 API 提供了僅在 etcd 上可用的表達性分散式特性。更重要的是,通過直接支援更多的語言,使用新的使用模式更容易為 etcd 編寫新的應用程式,從而幫助 etcd 變得更加穩定和可靠。
初級入門
你可以通過構建並執行一個名為 jetcdctl
的小例子程式來試用 jetcd,該程式使用了 jetcd 去訪問 etcd。對於更進一步的 jetcd 專案來說,jetcdctl 示例也是一個很好的起點。要繼續學習,你還需要同時安裝 Git 和 Java。
首先,克隆 jetcd 庫來獲取 jetcd 原始碼,然後使用 Maven 來構建 jetcd-simple-ctl
吧:
$ git clone https://github.com/coreos/jetcd.git
$ cd jetcd/jetcd-examples/jetcd-simple-ctl
$ ./mvnw clean package
複製程式碼
構建並準備好執行 jetcdctl
之後,下載一個 etcd 發行版並在本地啟動一個 etcd 服務。(譯者注:若以下 “go get” 命令無法正常執行,可以參考這裡的資料):
# build with “go get github.com/coreos/etcd/cmd/etcd”
$ etcd &
複製程式碼
接下來,使用 jetcdctl
將 123
寫入 abc
,與本地 etcd 伺服器進行通訊:
$ java -jar target/jetcdctl.jar put abc 123
21:39:06.126|INFO |CommandPut - OK
複製程式碼
你可以通過讀取 abc
來確認寫入 etcd 的 put 命令的正確性:
$ java -jar target/jetcdctl.jar get abc 21:41:00.265|INFO |CommandGet - abc 21:41:00.267|INFO |CommandGet - 123
複製程式碼
我們已經通過 get 和 put keys 演示了 jetcd 的基本功能。現在,讓我們進一步研究如何在程式碼中使用 jetcd 吧。
更好的 watches(觀察)特性
jetcd API 可以方便地管理 etcd 的底層 gRPC 協議。一個例子是 streaming key 事件,其中客戶端觀察 key,etcd 服務端不斷地往客戶端發回更新資訊。jetcd 客戶端管理著一個低階別的 gRPC 流,用來優雅地處理斷開連線,並向使用者呈現一個無縫的事件流。
如果 jetcd 應用程式希望接收到一個 key 的所有更新,它將使用 watch API 來建立一個 Watcher:
Watcher watch(ByteSequence key)
複製程式碼
Watcher
的 listen
方法從 etcd 中讀取 WatchResponse
訊息。每個 WatchResponse
包含被監視 key 上的最新事件序列。如果沒有任何事件,則 listen
被阻塞,直到有更新為止。listen
方法是可靠的;它不會在呼叫之間刪除任何事件,即使在斷開連線的情況下:
WatchResponse listen() throws InterruptedException
複製程式碼
總之,客戶端建立一個 Watcher
,然後使用 listen
來等待事件。下面是在 key abc
上進行觀察的程式碼,列印觀察到的 key 和 value,直到 listen
丟擲異常:總之,客戶端建立一個 Watcher
,然後使用 listen
來等待事件。下面是觀察 key abc
的程式碼,列印 key 和 value,直到 listen
丟擲異常:
Client client = Client.builder().endpoints(“http://127.0.0.1:2379).build();
Watcher watcher = client.getWatchClient().watch(ByteSequence.fromString("abc"));
while (true) {
for (WatchEvent event : watcher.listen().getEvents()) {
KeyValue kv = event.getKeyValue();
System.out.println(event.getEventType());
System.out.println(kv.getKey().toStringUtf8());
System.out.println(kv.getValue().toStringUtf8());
}
}
複製程式碼
將此特性與 Apache 基金會中與 etcd 對標的 ZooKeeper 進行比較。從 ZooKeeper 3.4.10 開始,watch 就已經是一次性觸發器,這意味著一旦收到一個 watch 事件,您必須設定一個新的 watch,以便在將來發生更改時得到通知。要傳輸金鑰事件,可會斷必須與叢集聯絡,為每個新事件註冊一個新的觀察者。
要在 key 更新時連續列印 key 的內容,ZooKeeper 應用程式首先建立一個 Watcher 來偵聽 WatchedEvent
訊息。觀察程式實現了一個事件回撥方法 process
,當 key 發生更改時就會呼叫該方法。要在事件中註冊興趣,觀察程式需要新增到 exists 方法中,該方法獲取 key 的後設資料(如果有的話)。當 key 發生變化時,觀察者的 process
方法就會呼叫 getData 來檢索 key 的值,然後再次註冊相同的觀察者來接收未來的更改,如下所示:
key = “/abc”;
Watcher w = new Watcher() {
public void process(WatchedEvent event) {
try {
System.out.println(event.getType());
System.out.println(event.getPath());
if (event.getType() != EventType.NodeDeleted) {
System.out.println(new String(zk.getData(event.getPath(), false, null)));
}
zk.exists(key, this);
} catch (Exception e) {
e.printStackTrace();
}
}
};
zk.exists(key, w);
複製程式碼
與 jetcd 示例不同,ZooKeeper 程式碼不能保證它觀察所有更改,因為在監視程式接收事件和傳送請求以獲取新監視之間存在延遲。例如,在執行 process
和呼叫 exists
以註冊新監視程式之間發生了一個事件。由於沒有註冊任何觀察程式,因此該事件永遠不會被觸發,並且會丟失。
即使假設所有事件都已觸發,程式碼仍然可能破壞事件流。沒有 etcd 提供的多版本併發控制,就無法訪問歷史 key。如果 key value 在接收事件和獲取資料之間發生了變化,程式碼將列印出最新的值,而不是與 watch 事件關聯的值。更糟的是,事件沒有附帶修訂資訊;無法確定 key 是來自事件還是來自 future 返回。
v0.0.1 版本以及未來計劃
從 v0.0.1 開始,jetcd 支援大多數應用程式需要的鍵值儲存。這些原語可以作為複雜模式(如分散式佇列、barriers 等)的構建塊。在未來,jetcd 將能夠使用 etcd 的本地鎖和領導人選舉 rpc 進行叢集範圍的標準化分散式協調。
jetcd 設計目的是易於使用,同時還能夠利用 etcd 的先進功能。它是開源的,並且正在活躍開發中,歡迎社群的貢獻和反饋。我們可以在 GitHub 上找到它,地址是github.com/coreos/jetc…。
如果發現譯文存在錯誤或其他需要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可獲得相應獎勵積分。文章開頭的 本文永久連結 即為本文在 GitHub 上的 MarkDown 連結。
掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。