基於 etcd 實現大規模服務治理應用實戰

一、服務治理概念介紹

服務治理是 IT 治理的一部分,它關注服務生命週期中的相關要素,其重點環節包括服務註冊和發現、服務平滑升級、流量監控、流量管控、故障定位、安全性等。

服務是需要 "治理" 的,但是治理是需要成本的,如果一個服務的業務邏輯簡單,運行流程清晰,出現問題也能及時定位和回滾,那麼該服務治理的成本可能非常低,甚至只需要人工處理就行,但是在複雜業務中,服務的提供者和服務的使用者可能分別運行在不同的進程中(甚至在不同的物理節點上),並由不同的團隊開發和維護。團隊協作和服務協同,都需要進行大量的協調工作。協調工作越多,複雜度越高,這樣就有了服務治理的需求,通過建設統一的服務治理平臺,就可以有有效的提升業務的服務治理能力,包括協同的規範化、實時監控,不斷優化調用鏈路的效率,以及輔助降低依賴複雜度,規避風險等。在大型業務系統中,服務治理已經是技術架構中必不可缺的一部分,也是整個業務系統最重要的基礎設施之一。

上圖是網上流傳的 netflix 的服務拓撲圖,圖中密密麻麻的白色小點就是 netflix 的服務節點,節點之間的連線表明服務之間有調用,節點和連線構成了複雜的服務調用鏈,如此龐大的應用系統必須要通過一個強力的服務治理平臺來進行管理。

服務治理本質上是對服務生命週期的管控,因而服務治理平臺的核心需求就是如何解決服務生命週期中的痛點問題,其包括以下幾個方面:

1、註冊和發現

服務調用方在調用服務之前必須要得到服務提供方的地址,也就是調用方需要通過一種方式 “發現“服務提供方,這就是服務發現。而要完成服務發現,就需要將服務提供方的信息存儲到某個載體,這個存儲的動作即是” 服務註冊 “,而存儲的載體則稱爲” 服務註冊中心“。在任何一個服務治理平臺中,"註冊中心" 是必不可少的一個模塊。服務註冊和發現是服務治理中最基礎的功能,在服務生命週期中,它負責服務的初始環節。

2、流量監控
在服務註冊發現之後,就是服務的調用,大量的服務調用,形成了流量。流量監控就是對衆多服務間的調用關係、狀態的清晰掌控。其主要包括了調用拓撲關係、調用追蹤、日誌、監控告警等,服務治理通過調用拓撲來整體監控服務調用關係,通過建立監控體系來快速發現、定位問題,從而在整體上感知業務系統的運行狀況。在服務生命週期中,流量監控負責服務的運行態感知。

3、流量調度
在業務系統運行過程中,經常會有比如促銷、秒殺、明星緋聞等熱點問題,或者機房斷網、斷電、系統大範圍升級等突發事件,帶來業務系統中局部服務的流量突增突降,這樣就需要對服務的流量進行調度和管理。流量管理包括兩個方面:從微觀的單個服務來說,就是服務調用過程的管理,包括在何時採用何種均衡負載策略、路由策略以及熔斷限流策略,這些策略統稱爲調用策略;從宏觀上來說,就是流量分發的管理,可以根據某些流量特徵和流量佔比進行灰度發佈、藍綠髮布等,這些稱爲流量分發策略。服務調用策略、流量分發策略,都需要通過流量監控收集的調用數據進行分析,從而制定出決策,然後在服務治理平臺上落地。流量調度負責服務的運行態管理。

4、服務控制
流量調度的策略如何在服務的提供方和調用方生效,可以重啓生效,也可以在運行態實時生效,這就是看服務治理平臺對服務的控制力度,服務治理平臺在充分建設服務治理能力後,能實時把服務治理的策略向服務進行分發並立即生效。

5、服務安全
每個服務都承載自身的業務職責,一些業務敏感的服務,需要對其他服務的訪問進行認證與鑑權,也就是安全問題。

本文把擁有成千上萬的服務稱之爲大型應用系統,該系統的特徵是大量的服務、大量的服務實例、以及海量的服務調用,服務治理平臺在管理這類業務系統的服務時,需要面對以下巨大的挑戰:

1.  高可靠性
大型業務系統,海量的服務調用,錯綜複雜的調用關係,對服務的可靠性要求很高,很多基層的服務都要求 99.99% 的可靠性,因而維護這些服務的服務治理平臺,其可靠性的要求也非常高,而要達到這麼高的可靠性,服務治理平臺本身也需要做到多級部署、多地熱備、降級隔離、平滑上線等方案。

2.  高性能
在保證可靠性的前提下,服務治理還必須有很高的性能,比如在監控數據中,快速準確的感知到某個服務的出現了單點故障,從而能夠將流量分發到該服務的其他進程上去。如果業務系統的服務數不多,調用量不高,那麼監控數據量也不會很大,服務的單點故障很容易就能查到,但是在實時的海量調用數據中,一些常規的查詢手段要花費大量的時間,等感知到單點故障時,可能已經造成了不可挽回的業務損失。所以性能是考量服務治理平臺治理能力的一項重要指標,如何保證高性能,高速的存儲、多級緩存、線性部署都是必不可少的。

3.  高擴展
高擴展包含兩個方面:大型應用系統的服務,可能是由多個團隊在開發運維,其水平和技術能力也是參差不齊的,因而服務治理平臺需要提供兼容和擴展的能力,通過擴展性,儘可能的把不同的服務治理起來;同時,在業務系統服務量增長時,服務治理平臺也應該具備同步擴展的能力,來保證其高可靠和高性能。

面對海量服務的治理挑戰,服務治理平臺也需要有一個強大好用的存儲工具來應對,etcd 就是一個不錯的選擇。

二、etcd 介紹

2.1 etcd 發展背景與相關競品介紹

2013 年 CoreOS 創業團隊在構建一款開源,輕量級的操作系統 ContainerLinux 時,爲了應對用戶服務多副本之間協調的問題,自研開發的一款用於配置共享和服務發現的高可用 KV 分佈式存儲組件——ETCD。

下面我們也針對 Zookeeper 和 Consul 兩個選型做了一下對比:

·       ZooKeeper
ZooKeeper 從高可用性,數據一致性,功能這三個方面而言是完全符合需求的,但 CoreOS 還是堅持自研 etcd 的原因總結有以下兩點:

  1.  ZooKeeper 不支持通過 API 安全地變更成員,需要人工修改節點配置並重啓進程. 如果操作有誤,有可能導致腦裂等線上故障,同時 CoreOS 對適配雲環境,集羣規模的平滑調整,運行時配置的在線變更都是有期望目標的,這方面 ZooKeeper 的維護成本比較高。

2.  高負載讀寫性能,ZooKeeper 在大規模的實例連接情況下性能表現並不佳。

etcd 名字是由 “/etc” 文件夾和”d” 分佈式系統組成。“/etc” 文件夾是用來存儲單系統配置數據的,而 “etcd” 用於存儲大規模分佈式系統的配置數據,etcd 集羣可提供高穩定性,高可靠性,高伸縮性和高性能的分佈式 KV 存儲服務。etcd 是基於複製狀態機實現的,由 Raft 一致性模塊,日誌模塊,基於 boltdb 持久化存儲的狀態機組成,可應用於分佈式系統的配置管理,服務發現,分佈式一致性等等。

ZooKeeper 與 etcd 一樣,可解決分佈式系統一致性和元數據存儲等問題,但是 etcd 相較於 ZooKeeper 有以下幾點優勢:

1.  動態集羣成員關係重新配置

2.  高負載下穩定的讀寫能力

3.  多版本併發控制數據模型

4.  可靠的鍵監控

5.  Lease(租約) 原語將連接和會話分離

6.  分佈式鎖保證 API 安全性

  1.  ZooKeeper 使用自己的 RPC 協議,使用受限;而 etcd 客戶端協議是基於 gRPC 的,可支持多種語言。

·       Consul

Consul 與 etcd 解決的是不同的問題,etcd 用於分佈式一致性 KV 存儲,而 Consul 側重於端到端的服務發現,它提供了內置的健康檢查,失敗檢測和 DNS 服務等等,另外 Consul 通過 RESTfulHTTPAPIs 提供 KV 存儲能力. 但是當 KV 使用量達到百萬級時,會出現高延遲和內存壓力等問題。

一致性算法方面,etcd、Consul 基於 Raft 算法實現數據複製,ZooKeeper 則是基於 Zab 算法實現。Raft 算法由 Leader 選舉,日誌同步,安全性組成,而 Zab 協議則由 Leader 選舉、發現、同步、廣播組成。

分佈式 CAP 方面,etcd、Consul 和 ZooKeeper 都是 CP 系統,發生網絡分區時,無法寫入新數據。

下表是針對三者的關鍵能力做了一下對比分析:

2.2 etcd 核心技術介紹

基於 Raft 協議實現數據高可用和強一致性

早期數據存儲服務引入多副本複製技術方案來解決單點問題,但是無論是主從複製還是去中性化複製,都存在一定的缺陷。主從複製運維困難,且一致性與可用性難以兼顧;去中心化複製,存在各種寫入衝突問題需要業務處理。而分佈式一致性算法,正是解決多副本複製存在問題的關鍵。分佈式一致性算法,又稱爲共識算法,最早是基於複製狀態機背景下提出來的。Paxos 作爲第一個共識算法,過於複雜,不容易理解,難以在工程上落地。斯坦福大學的 Diego 提出的 Raft 算法,通過將問題拆解爲三個子問題,易於理解,降低了工程落地難度。這三個子問題是:Leader 選舉,日誌複製,安全性。

Leader 選舉

etcd(版本 3.4+) 中 Raft 協議定義集羣節點有 4 種狀態:Leader、Follower、Candidate、PreCandidate。

正常情況下,Leader 節點會按照心跳間隔時間,定時廣播心跳消息給 Follower 節點,以維持 Leader 身份。Follower 收到後回覆心跳應答包消息給 Leader。Leader 都會帶有一個任期號 (term),任期表示從一次選舉開始,贏得選舉的節點在該任期內擔當 Leader。任期號單調遞增,在 Raft 算法中充當邏輯時鐘,用於比較各個節點數據新舊,識別過期 Leader 等等。

當 Leader 節點異常時,Follower 節點會接收 Leader 的心跳消息超時,當超時時間大於競選超時時間後,會進入 PreCandidate 狀態,不自增任期號,僅發起預投票 (民意調查,防止由於節點數據遠遠落後於其他節點而發起無效選舉),獲得大多數節點認可後,進入 Candidate 狀態. 進入 Candidate 狀態的節點,會等待一個隨機時間,然後發起選舉流程,自增任期號,投票給自己,並向其他節點發送競選投票信息。

當節點 B 收到節點 A 競選消息後,有 2 種情況:

  1.  節點 B 判斷節點 A 的數據至少和自己一樣新,節點 A 任期號大於節點 B 任期號,並且節點 B 未投票給其他候選者,即可投票給節點 A,節點 A 獲得集羣大多數節點支持,可成爲新 Leader。

  2.  如果節點 B 也發起了選舉,並投票給自己,那麼它將拒絕投票給節點 A。此時若沒有節點可以得到大多數投票支持,則只能等待競選超時,開啓新一輪選舉。

日誌複製

Raft 日誌結構如下圖所示:

Raft 日誌由有序索引的一個個條目組成,每個日誌條目包含了任期號和提案內容. Leader 通過維護兩個字段來追蹤各個 Follower 的進度信息. 一個是 NextIndex,表示 Leader 發送給該 Follower 節點的下一個日誌條目索引; 另一個是 MatchIndex,表示該 Follower 節點已複製的最大日誌條目索引。

本文以 Client 提交 “hello=world” 提案,至接收到響應的整個流程爲例,簡單介紹 etcd 日誌複製流程:

  1.  當 Leader 接收到 Client 提交的提案信息後,生成日誌條目,同時遍歷各個 Follower 的日誌進度,生成對各個 Follower 追加日誌的 RPC 消息;

  2.  通過網絡模塊將追加日誌的 RPC 消息廣播給各個 Follower;

  3.  Follower 接收到追加日誌消息並持久化之後,回覆 Leader 已複製最大日誌條目索引,即 MatchIndex;

  4.  Leader 接收到 Follower 應答後,更新對應 Follower 的 MatchIndex;

  5.  Leader 根據各個 Follower 提交的 MatchIndex 信息,計算出日誌條目已提交索引位置,該位置代表日誌條目被一半以上節點持久化;

  6.  Leader 通過心跳告知各個 Follower 已提交日誌索引位置;

  7.  當 Client 的提案,被標識爲已提交後,Leader 回覆 Client 該提案通過。

通過以上流程,Leader 同步日誌條目給各個 Follower,保證 etcd 集羣的數據一致性。

安全性

etcd 通過給選舉和日誌複製增加了一系列規則,來保證 Raft 算法的安全性。

選舉規則:

  1.  一個任期號,只能有一個 Leader 被選舉,Leader 選舉需要集羣一半以上節點支持;

  2.  節點收到選舉投票時,如果候選者最新日誌條目的任期號小於自己,拒絕投票,任期號相同但是日誌比自己短,同樣拒絕投票。

日誌複製規則:

  1.  Leader 完全特性,如果某個日誌條目在某個任期號中已被提交,則這個日誌條目必然出現在更大任期號的所有 Leader 中;

  2.  只附加原則,Leader 只能追加日誌條目,不能刪除已持久化的日誌條目;

  3.  日誌匹配特性,Leader 發送日誌追加信息時,會帶上前一個日誌條目的索引位置 (用 P 表示) 和任期號,Follower 接收到 Leader 的日誌追加信息後,會校驗索引位置 P 的任期號與 Leader 是否一致,一致才能追加。

boltdb 存儲技術

ectd 的另一個核心技術是 boltdb 存儲,提供高效的 b + 樹的檢索能力,同時支持事務操作,他是支撐 etcd 高性能讀寫的關鍵能力之一。

boltdb 的實現參見了 LMDB(LightningMemory-MappedDatabase) 設計思路,基於高效快速的內存映射數據庫方案. 基於 B + 樹的結構設計。數據文件設計上 bolt 使用一個單獨的內存映射的文件,實現一個寫入時拷貝的 B + 樹,這能讓讀取更快。而且,BoltDB 的載入時間很快,特別是在從 crash 恢復的時候,因爲它不需要去通過讀 log(其實它壓根也沒有)去找到上次成功的事務,它僅僅從兩個 B + 樹的根節點讀取 ID。

文件存儲設計

由於採用了單文件映射存儲,所以 bolt 對文件按指定長度進行分塊處理,每塊存儲不同的內容類型。默認使用 4096 字節的長度進行分塊。每一塊的開頭有單獨的 pageid(int64) 標識。

文件塊的類型有以下幾種:

FoNYIE

數據文件全景結構

說明:

單文件方案的優勢就是不需要做文件的合併刪除等操作,只需要在原文件上追加擴展長度就可以了。

查詢設計

boltdb 提供了非常高效的查詢能力,可以先看一下它的對象設計:

從對象設計上,boltdb 在加載時,會先 loadmeta 數據進內存,然後根據 bucket,來定位數據塊所在的位置,然後再根據 key 的值,來定位 branchnode 的位置,然後定位到葉子值節點。

我們以查詢爲例,來講解一下,下面是一個基本的查詢示例代碼:

tx, err := db.Begin(true) // 開啓事務
  if err != nil {
      return
  }
  b := tx.Bucket([]byte("MyBucket")) // 根據名稱查詢bucket
  v := b.Get([]byte("answer20")) // 根據key進行查詢 
  fmt.Println(string(v))
  tx.Commit()

對應上面的代碼,下面的序列圖,可以更詳細的瞭解一次查詢的操作流程:

上面最關鍵的代碼就是 search 方法,下面是主要的代碼片斷,已添加了註釋說明方便閱讀。

func (c *Cursor) search(key []byte, pgid pgid) {
    p, n := c.bucket.pageNode(pgid)
    if p != nil && (p.flags&(branchPageFlag|leafPageFlag)) == 0 {
        panic(fmt.Sprintf("invalid page type: %d: %x", p.id, p.flags))
    }
    // 把當前查詢節點(page,node)壓入棧
    e := elemRef{page: p, node: n}
    c.stack = append(c.stack, e)
    // If we're on a leaf page/node then find the specific node.
    if e.isLeaf() {
        c.nsearch(key)
        return
    }
    // if node cached seach by node's inodes field
    if n != nil {
        c.searchNode(key, n)
        return
    }
    // recursively to load branch page and call search child node again
    c.searchPage(key, p)
}

三、百度基於 etcd 打造大規模服務治理建設思路

3.1 具體的挑戰

天路是百度小程序團隊開發打造的面向大型業務服務治理需求的一套解決方案,其目標之一就是打造成百度的服務治理規範樣板。天路由註冊中心、可視化管理平臺、SDK 框架、統一網關、tianlu-mesher 五個部分組成,目前已經接入了 150 + 產品線,實例數已達數十萬級別。隨着接入平臺的團隊數增多、以及服務實例的快速增長,大量團隊間如何輕鬆的協作以及實現大規模服務治理平臺的高可用、高性能一直是天路持續面臨的挑戰。

3.2 整體架構建設思路與方案

天路作爲一個服務治理平臺,核心理念是爲所有的服務提供便捷的調用,統一的服務監控管理,簡化服務的開發和維護成本。我們從以下不同的方面思考基於 etcd 打造大規模服務治理平臺:高可用、高性能、高擴展、易用性。

·       高可用

·       高性能

·       高擴展

·       易用性

架構方案圖

3.3 關鍵的指標與運維目標

此外針對更好的實施服務治理平臺的運維,還需要以下的關鍵考覈指標與運維要求。

關鍵指標:

·       可用性達 99.99 以上;

·       平響 100ms 以下。

運維目標:

·       配置監控告警,包括註冊中心實例健康、etcd 平響、內存和 cpu 監控。

·       自動處理:通過 noah 的回調機制,自動處理一些故障,提高處理速度。

·       手動處理:值班機制。

四、總結

服務治理目前越來越被企業建設所重視,特別現在雲原生,微服務等各種技術被更多的企業所應用,但是要真正在應用好,融合好,還是有非常多的挑戰,除了一套成熟的服務治理產品外,包括團隊整體對服務治理的認知,技術經驗的深澱,遵循服務化的設計能力水平的能力等,都會影響到最終的實施效果。本文也僅在服務治理產品選型上給大家一些啓發,希望在服務治理的道路上幫大家走得更好更穩。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/1VmMZlMEv-In9QKYeYOjiA