etcd 笔记(05)— etcd 代码结构、各模块功能、整体架构、各模块之间的交互、请求和应答流程
1. etcd 項目結構和功能
etcd 項目代碼的目錄結構如下:
$ tree
├── auth
├── build
├── client
├── clientv3
├── contrib
├── embed
├── etcdctl
├── etcdmain
├── etcdserver
├── functional
├── hack
├── integration
├── lease
├── logos
├── mvcc
├── pkg
├── proxy
├── raft
├── scripts
├── security
├── tests
├── tools
├── vendor
├── version
└── wal
每個模塊的功能如下:
etcd 核心的模塊有 lease、mvcc、raft、etcdserver,其余都是輔助的功能。其中 etcdserver 是其他模塊的整合。
2. etcd 整體架構
etcd 整體架構圖如下:
2.1 客戶端層
包括 clientv3 和 etcdctl 等客戶端。用戶通過命令行或者客戶端調用提供了 RESTful 風格的 API,降低了 etcd 的使用復雜度。
除此之外,客戶端層的負載均衡(etcd V3.4 版本的客戶端默認使用的是 Round-robin,即輪詢調度)和節點間故障轉移等特性,提升了 etcd 服務端的高可用性。需要注意的是,etcd V3.4 之前版本的客戶端存在負載均衡的 Bug,如果第一個節點出現異常,訪問服務端時也可能會出現異常,建議進行升級。
2.2 API 接口層
API 接口層提供了客戶端訪問服務端的通信協議和接口定義,以及服務端節點之間相互通信的協議。
etcd 有 V3 和 V2 兩個版本。
etcd V3使用gRPC作為消息傳輸協議;etcd V2默認使用HTTP/1.x協議。
對于不支持 gRPC 的客戶端語言,etcd 提供 JSON 的 grpc-gateway 。通過 grpc-gateway 提供 RESTful代理,轉換 HTTP/JSON 請求為 gRPC 的 Protocol Buffer 格式的消息。
2.3 etcd Raft 層
負責 Leader 選舉和日志復制等功能,除了與本節點的 etcd Server 通信之外,還與集群中的其他 etcd 節點進行交互,實現分布式一致性數據同步的關鍵工作。
2.4 邏輯層
etcd 的業務邏輯層,包括鑒權、租約、KVServer、MVCC 和 Compactor 壓縮等核心功能特性。
2.5 etcd 存儲
實現了快照、預寫式日志 WAL(Write Ahead Log)。etcd V3 版本中,使用 BoltDB 來持久化存儲集群元數據和用戶寫入的數據。
3. 各個模塊之間的交互
下圖中展示了 etcd 處理一個客戶端請求涉及的模塊和流程。
從上至下依次為 客戶端 → API 接口層 → etcd Server → etcd raft 算法庫。我們根據請求處理的過程,將 etcd Server 和 etcd raft 算法庫單獨說明。
3.1 etcd Server
接收客戶端的請求,在上述的 etcd 項目代碼中對應 etcdserver 包。請求到達 etcd Server 之后,經過 KVServer 攔截,實現諸如日志、Metrics 監控、請求校驗等功能。
etcd Server 中的 raft 模塊,用于與 etcd-raft 庫進行通信。
applierV3 模塊封裝了 etcd V3 版本的數據存儲;WAL 用于寫數據日志,WAL 中保存了任期號、投票信息、已提交索引、提案內容等,etcd 根據 WAL 中的內容在啟動時恢復,以此實現集群的數據一致性。
3.2 etcdraft
etcd 的 raft 庫。raftLog 用于管理 raft 協議中單個節點的日志,都處于內存中。
raftLog 中還有兩種結構體 unstable 和 storage,這兩種結構體分別用于不同步驟的存儲,區別如下
unsable中存儲不穩定的數據,表示還沒有commit;storage中都是已經被commit了的數據;
除此之外,raft 庫更重要的是負責與集群中的其他 etcd Server 進行交互,實現分布式一致性。
3.3 交互細節
在上圖中,客戶端請求與 etcd 集群交互包括如下兩個步驟:
-
首先是寫數據到
etcd節點中; -
其次是當前的
etcd節點與集群中的其他etcd節點之間進行通信,確認存儲數據成功之后回復客戶端;
請求流程可劃分為以下的子步驟:
-
客戶端通過負載均衡算法選擇一個
etcd節點,發起gRPC調用; -
etcd Server收到客戶端請求; -
經過
gRPC攔截、Quota校驗,Quota模塊用于校驗etcd db文件大小是否超過了配額; -
接著
KVServer模塊將請求發送給本模塊中的raft,這里負責與etcd raft模塊進行通信; -
發起一個提案,命令為
put foo bar,即使用put方法將foo更新為bar; -
在
raft中會將數據封裝成raft日志的形式提交給raft模塊; -
raft模塊會首先保存到raftLog的unstable存儲部分; -
raft模塊通過raft協議與集群中其他etcd節點進行交互。
需要注意的是,在 raft 協議中寫入數據的 etcd 必定是 leader 節點,如果客戶端提交數據到非 leader 節點時,該節點需要將請求轉發到 etcd leader 節點處理。
響應流程的步驟如下:
-
提案通過
RaftHTTP網絡模塊轉發,集群中的其他節點接收到該提案; -
在收到提案之后,集群中其他節點向
leader節點應答“我已經接收這條日志數據”; -
Leader收到應答之后,統計應答的數量,當滿足超過集群半數以上節點,應答接收成功; -
etcd raft算法模塊構造Ready結構體,用來通知etcd Server模塊,該日志數據已經被commit; -
etcd Server中的raft模塊(交互圖中有標識),收到Ready消息后,會將這條日志數據寫入到WAL模塊中; -
正式通知
etcd Server該提案已經被commit; -
etcd Server調用applierV3模塊,將日志寫入持久化存儲中; -
etcd Server應答客戶端該數據寫入成功; -
etcd Server調用etcd raft庫,將這條日志寫入到raftLog模塊中的storage;
上述過程中,提案經過網絡轉發,當多數 etcd 節點持久化日志數據成功并進行應答,提案的狀態會變成已提交。
在應答某條日志數據是否已經 commit 時,為什么 etcd raft 模塊首先寫入到 WAL 模塊中?
這是因為該過程僅僅添加一條日志,一方面開銷小,速度會很快;另一方面,如果在后面 applierV3 寫入失敗,etcd 服務端在重啟的時候也可以根據 WAL 模塊中的日志數據進行恢復。etcd Server 從 raft 模塊獲取已提交的日志條目,由 applierV3 模塊通過 MVCC 模塊執行提案內容,更新狀態機。
整個過程中,etcd raft 模塊中的 raftLog 數據在內存中存儲,在服務重啟后失效;客戶端請求的數據則被持久化保存到 WAL 和 applierV3 中,不會在重啟之后丟失。
參考:
https://kaiwu.lagou.com/course/courseInfo.htm?courseId=613#/detail/pc?id=6403
總結
以上是生活随笔為你收集整理的etcd 笔记(05)— etcd 代码结构、各模块功能、整体架构、各模块之间的交互、请求和应答流程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2022-2028年中国ITO薄膜行业市
- 下一篇: 2022-2028年中国硅酸钙板行业市场