ETCD應用場景
https://tonydeng.github.io/2015/10/19/etcd-application-scenarios/
etcd是什麼?
很多人對這個問題的第一反應可能是,它是一個鍵值儲存倉庫,卻沒有重視官方定義的後半句,用於配置共享和服務發現。
A highly-available key value store for shared configuration and service discovery.
實際上,etcd作為一個受到Zookeeper和doozer啟發而催生的專案,除了擁有與之類似的功能外,更具有以下4個特點。(引自etcd官方文件)
- 簡單: 基於HTTP+JSON的API讓你可以用CURL命令就可以輕鬆使用。
- 安全: 可以選擇SSL客戶認證機制。
- 快速: 每個例項每秒支援一千次寫操作。
- 可信: 使用Ralf演算法充分實現了分散式。
應用場景
場景一: 服務發現
服務發現(Service Discovery)要解決的是分散式系統中最常見的問題之一,即在同一個分散式叢集中的程序或服務如何才能找到對方並建立連線。
從本質上說,服務發現就是要了解叢集中是否有程序在監聽upd或者tcp埠,並且通過名字就可以進行查詢和連結。
要解決服務發現的問題,需要下面三大支柱,缺一不可。
- 一個強一致性、高可用的服務儲存目錄。
- 基於Ralf演算法的etcd天生就是這樣一個強一致性、高可用的服務儲存目錄。
- 一種註冊服務和健康服務健康狀況的機制。
- 使用者可以在etcd中註冊服務,並且對註冊的服務配置
key TTL
- 使用者可以在etcd中註冊服務,並且對註冊的服務配置
- 一種查詢和連線服務的機制。
- 通過在etcd指定的主題下注冊的服務也能在對應的主題下查詢到。
- 為了確保連線,我們可以在每個服務機器上都部署一個proxy模式的etcd,這樣就可以確保訪問etcd叢集的服務都能夠互相連線。
下面我們來看一下服務發現的具體應用場景
微服務協同工作架構中,服務動態新增。
隨著Docker容器的流行,多種微服務共同協作,構成一個功能相對強大的架構的案例越來越多。透明化的動態新增這些服務的需求也日益強烈。通過服務發現機制,在etcd中註冊某個服務名字的目錄,在該目錄下儲存可用的服務節點的IP。在使用服務的過程中,只要從服務目錄下查詢可用的服務節點進行使用即可。
微服務協同工作如下圖:
PaaS平臺中應用多例項與例項故障重啟透明化
PaaS平臺中的應用一般都有多個例項,通過域名,不僅可以透明的對多個例項進行訪問,而且還可以實現負載均衡。
但是應用的某個例項隨時都有可能故障重啟,這時就需要動態的配置域名解析(路由)中的資訊。通過etcd的服務發現功能就可以輕鬆解決這個動態配置的問題。
場景二: 訊息釋出和訂閱
在分散式系統中,最為適用的元件間通訊的方式是訊息釋出和訂閱機制。
具體而言,即配置一個配置共享中心,書籍提供者在這個配置中心釋出訊息,而訊息使用者則訂閱他們關心的主題,一旦有關主題有訊息釋出,就會實時通知訂閱者。通過這種方式可以實現釋出式系統配種的集中式管理和實時動態更新。
應用中的一些配置新存放在etcd上進行集中管理
這類場景的使用方式通常是這樣的:
應用在啟動的適合主動從etc獲取一次配置資訊,同時,在etcd節點上註冊一個Watcher
並等待,以後每次配置有更新的適合,etcd都會實時通知訂閱者,以此達到獲取最新配置資訊的目的。
分散式日誌收集系統
這個系統的核心工作是收集分佈在不同機器上的日誌。
收集器通常按應用(或主題)來分配收集任務單元,因此可以在etcd上建立一個以應用(或主題)名目的目錄,並將這個應用(或主題)相關的所有機器IP以子目錄的形式儲存在目錄下。然後設定一個遞迴的etcd Watcher,遞迴式的健康應用(或主題)目錄下所有資訊的變動。這樣就實現了在機器IP(訊息)發生變動時,能夠實時接受收集器調整任務分配。
系統中心需要動態自動獲取與人工干預修改資訊請求內容
通常的解決方案是對外保留介面,例如JMX介面,來獲取一些執行時的資訊或提交修改的請求。
而引入etcd後,只需要將這些資訊存放在指定的etcd目錄中,即可通過http介面直接被外部訪問。
場景三: 負載均衡
在場景一中也提到了負載均衡(即軟體負載均衡)。
在分散式系統中,為了保證服務的高可用以及資料一致性,通常都會把資料和服務部署多份,以此達到對等服務,即使其中的某一個服務失效了,也不影響使用。
這樣的實現誰讓會導致一定程度上資料寫入效能的下降,但是卻能夠實現資料訪問時的負載均衡。因為每個對等服務節點上都存有完整的資料,所有使用者的訪問流量就可以分流道不同的機器上。
etcd本身分散式架構儲存的資訊支援負載均衡
etcd叢集化以後,每個etcd的核心節點都可以處理使用者的請求。所以,把資料量小但是訪問頻繁的訊息資料直接儲存到etcd是一個不錯的選擇。比如,業務系統中常用的二級程式碼表。
二級程式碼表的工作過程一般是這樣,在表中儲存程式碼,在etcd儲存程式碼所代表的具體換衣,業務系統呼叫查表的過程,就需要查看錶中程式碼的含義。所以如果把二級程式碼表中的小量資料儲存到etcd中,不僅方便修改,也易於大量訪問。
利用etcd維護一個負載均衡節點表
etcd可以監控一個叢集中多個節點的狀態,當有一個請求發過來後,可以輪詢式把請求轉發給存活的多個節點。類似KafkaMQ,通過Zookeeper來維護生產者和消費者的負載均衡(也可以用etcd來做Zookeeper的工作)。
場景四: 分散式通知與協調
這裡討論的分散式通知和協調,與訊息釋出和訂閱有點相似。兩者都使用了etcd的Watcher
機制,通過註冊與非同步通知機制,實現分散式環境下的不同系統之間的通知與協調,從而對資料變更進行實時處理。
實現方式通常為:
不同系統都在etcd上對同一個目錄進行註冊,同時設定Watcher
監控該目錄的變化(如果對子目錄的變化也有需求,可以設定成遞迴模式),當某個系統更新了etcd的目錄,那麼設定了Watcher
的系統就會受到通知,並做出相應的通知,並作出相應處理。
通過etcd進行低耦合的心跳檢測
檢測系統和被檢測系統通過etcd上某個目錄管理而非直接關聯起來,這樣可以大大減少系統的耦合性。
通過etcd完成系統排程
某系統有控制檯和推送系統兩部分組成,控制檯的職責是控制推送系統進行相應的推送工作。管理人員在控制檯做的一些操作,實際上只需要修改etcd上某些目錄節點的狀態,而etcd就會自動把這些變化通知給註冊了Watcher
的推送系統客戶端,推送系統再作出相應的推送任務。
通過etcd完成工作彙報
大部分類似的任務分發系統,子任務啟動後,到etcd來註冊一個臨時工作目錄,並且定時將自己的進度彙報(將進度寫入到這個臨時目錄),這樣任務管理者就能夠實時知道任務進度。
場景五: 分散式鎖
因為etcd使用Raft
演算法保持了資料的強一致性,某次操作儲存到叢集中的值必然是全域性一致的,所以很容易實現分散式鎖。
鎖服務有兩種使用方式,一是保持獨佔,二是控制時序。
保持獨佔
即所有試圖獲取鎖的使用者最終只有一個可以得到。
etcd為此提供了一套實現分散式鎖原子操作CAS(ComparaAndSwap
)的API。通過設定prevExist
值,可以保證在多個節點同時建立某個目錄時,只有一個成功,而該使用者即可任務是獲得了鎖。
控制時序
即所有試圖獲取鎖的使用者都會進入等待佇列,獲得鎖的順序是全域性唯一的,同時決定了佇列執行順序。
etcd為此也提供了一套API(自動建立有序鍵),對一個目錄建值是指定為POST
動作,這樣etcd就會在目錄下生成一個當前最大的值為鍵,儲存這個新的值(客戶端編號)。
同時還可以使用API按順序列出所有目錄下的鍵值。此時這些鍵的值就是客戶端的時序,而這些鍵中儲存的值可以是代表客戶端的編號。
場景六: 分散式佇列
分散式佇列的常規用法與場景五中所描述的分散式鎖的控制時序用法類似,即建立一個先進先出的佇列,保證順序。
另一種比較有意思的實現是在保證佇列達到某個條件時再統一按順序執行。這種方法的實現可以在/queue
這個目錄中另外再建立一個/queue/condition
節點。
- condition可以表示佇列大小。比如一個大的任務需要很多小任務就緒的情況下才能執行,每次有一個小任務就緒,就給這個condition數字加1,直到達到大任務規定的數字,再開始執行佇列裡的一系列小任務,最終執行大任務。
- condition可以表示某個任務不在佇列。這個任務可以是所有排序任務的首個執行程式,也可以是拓撲結構中沒有依賴的點。通常,必須執行這些任務後才能執行佇列中的其他任務。
- condition還可以表示其它的一類開始執行任務的通知。可以由控制程式指定,當condition出現變化時,開始執行佇列任務。
場景七: 叢集監控與Leader競選
通過etcd來進行監控實現起來非常簡單並且實時性強,用到了以下兩點特性:
- 前面幾個場景已經提到了Watcher機制,當某個節點消失或由變動時,Watcher會第一時間發現並告知使用者。
- 節點可以設定
TTL key
,比如每隔30s向etcd傳送一次心跳使代表該節點依然存活,否則說明節點消失。
這樣就可以第一時間檢測到各節點的健康狀態,以完成叢集的監控要求。
另外,使用分散式鎖,可以完成Leader競選。對於一些長時間CPU計算或使用IO操作,只需要由競選出的Leader計算或處理一次,再把結果複製給其他Follower即可,從而避免重複勞動,節省計算資源。
Leader應用的經典場景是在搜尋系統中建立全量索引。如果每個機器分別進行索引的建立,不僅耗時,而且不能保證索引的一致性。通過在etcd的CAS機制競選Leader,由Leader進行索引計算,再降計算結果分發到其他節點。
場景八: 為什麼使用etcd而不用Zookeeper?
閱讀了“Zookeeper典型應用場景一覽”的同學可能會發現,etcd實現的這些功能,Zookeeper都能實現。那為什麼要用etcd而非直接使用Zookeeper呢?
相比較之下,Zookeeper有如下缺點。
- 複雜。 Zookeeper的部署維護複雜,管理員必須掌握一系列的知識和技能;而Paxos強一致性演算法也是素來以複雜難懂而聞名於世;另外,Zookeeper的使用也比較複雜,需要安裝客戶端,官方只提供Java和C的兩種語言的介面。
- Java編寫。這裡不是對Java有偏見,而是Java本身就偏向重型應用,它會引入大量的依賴。而運維人員則普遍希望機器叢集能儘可能的簡單,維護起來也不容易出錯。
- 發展緩慢。 Apache基金會專案特有的“Apache Way”在開源界也飽受爭議,其中一大原因就是由於基金會龐大的結構和鬆散的管理導致專案發展緩慢。
而etcd作為一個後起之秀,其優點也很明顯。
- 簡單。 使用Go編寫部署簡單;使用HTTP作為介面使用簡單;使用Raft演算法保證強一致性讓使用者易於理解。
- 資料持久化。 etcd預設資料一更新就進行持久化。
- 安全。 etcd支援SSL客戶端安全認證。
最後,etcd作為一個年輕的專案,正在高速迭代和開發中,這既是一個優點,也是一個缺點。
優點是在於它的未來具有無限的可能性,缺點是版本的迭代導致其使用的可靠性無法保證,無法得到大專案長時間使用的校驗。
然而,目前CoreOS、Kubernetes和Cloudfoundry等知名專案均在生產環境中使用了etcd,所以總的來說,etcd值得你去嘗試。