ZooKeeper 在阿里巴巴的服務形態演進

語言: CN / TW / HK

作者:草谷

Apache ZooKeeper 在阿里巴巴經歷了開源自用、深度優化、反哺社群、開發企業版服務雲上客戶的演進過程,為了釐清本文脈絡,我們對演進過程中提到的關鍵名詞做以下定義。

  • Apache ZooKeeper:提供分散式協調服務如分散式鎖、分散式佇列等,還可用於註冊配置中心的能力。
  • TaoKeepeer:基於 ZooKeeper 做了深度改造,於2008年服務於淘寶。
  • MSE:阿里雲的一個面向業界主流開源微服務生態的一站式微服務平臺。
  • ZooKeeper 企業服務:MSE 的子產品,提供開源增強的雲上服務,分為基礎版和專業版兩種。

ZooKeeper 在阿里巴巴的服務形態演進歷程

早在 2008 年,阿里巴巴基於 ZooKeeper 的開源實現和淘寶的電商業務,設計 Taokeeper 這款分散式協調軟體,彼時恰逢淘寶啟動服務化改造,那時候,也誕生了各類分散式中介軟體,例如 HSF/ConfigServer/VIPServer 等。

10 年後的 2019 年,阿里巴巴實施全站上雲戰役,所有的產品都需要升級到公有云架構,MSE 就是在那個時候誕生的,上線後便相容了主流的 ZooKeeper 版本。

1.png

整個過程經歷了以下 3 個階段:

第一個階段:08 年的 1.0 版本,主要支援集團有分散式協調需求的應用,那時候所有的業務都是混著用,有 1000 多個應用,最終大概手動運維著 150+個共享叢集。隨著時間的推移,業務都在做微服務拆分,共享叢集的容量爆炸式增長,這樣帶來的問題就是:業務混部,爆炸半徑大,穩定性存在著很大的風險;日常的運維,例如機器置換等,牽一髮而動全身,如果配置出問題,影響所有業務。

第二個階段:為了解決階段一的問題,我們將 ZooKeeper 演進到 2.0 版本。那時候正直容器化剛剛興起,在仔細研究過容器化的改造方案後,我們在效能和運維能夠同時滿足要求的情況下,進行了大量的改造,業務進行拆分、叢集遷移、按最小穩定單元去運維一個叢集,這樣我們終於可以睡個安穩覺了,拆分完後,依託於 K8s 的規模化運維能力,這些問題都得到了很好的解決,由此實現了獨享模式叢集、資源隔離,SLA 得到了提升,能到達 99.9%。

第三個階段:上雲提供公共雲服務,也就演進到了 3.0。這個版本重點打造了開源增強,例如,基於 Dragonwell 進行構建、JVM 引數調優、集成了 Prometheus、部署形態多 AZ 強制平均打散、支援動態配置 、平滑擴縮容等改造,在效能、免運維、可觀測、高可用和安全等方面做了諸多提升,SLA 能夠到達 99.95%。

2.png

ZooKeeper 在技術場景上的最佳實踐

接下來,給大家介紹下 ZooKeeper 的最佳實踐場景,歸為了 3 類,分別是:

  • 微服務領域,代表的整合產品是 Dubbo/SpringCloud
  • 大資料領域,代表的整合產品是 Flink/Hbase/Hadoop/Kafka
  • 自研的分散式系統,包括大家自己公司內部的分散式系統,對分散式協調有需求,如分散式鎖

微服務領域-註冊中心

ZooKeeper 在微服務場景裡面,主要是用作註冊中心,利用了 ZooKeeper 的註冊/訂閱模式,可以看下 Dubbo 在 ZooKeeper 裡面的資料結構:

3.png

在 Provider 啟動時,會向 ZooKeeper 固定路徑 providers 下面建立一個臨時節點, 在這個節點裡面存入本機的服務資訊,例如,應用名,IP 和埠等,Consumer 啟動的時候 ,監聽對應服務下 Providers 的所有子節點,ZooKeeper 會把所有子節點資訊主動通知到 Consumer,Consumer 此時就拿到所有 Provider 的地址列表資訊了,Provider 註冊到 ZooKeeper 上面的臨時節點,它的生命週期和 Provider 與ZooKeeper 之間建立的長連結時一致的,除非 Provider 主動下線,當 Provider 宕機或者主動下線,這個臨時節點就會被刪除,那麼訂閱這個服務的 Consumer 們,會通過 Watch 監聽到事件,更新一下地址列表,把它摘除調。

4.png

在這裡有 2 個注意的點:

  • 註冊到 ZooKeeper 的服務資料,不要太多,在 Provider 或者 Consumer 非常多的情況下,頻繁上下線的時候,非常容易導致 ZooKeeper FullGC。

  • Provider 在非正常下線時,臨時節點的生命週期取決於 SessionTimeOut 的時間,這個可以根據業務自行設定,避免過長或者過短影響業務呼叫。

大資料領域-HA 高可用

在大資料領域,Flink/Hadoop/Hbase/Kafka 等系統都預設的把 ZooKeeper 當作分散式協調的元件,在這裡面,ZooKeeper 利用自己的特性,幫助它們解決了非常多的分散式問題,其中最主要的就是利用 ZooKeeper 做了 HA(Highly Available)方案,提高叢集可用性,一般有兩個或兩個以上的節點,且分為活動節(Active)點及備用節點(standby)。

下方圖例中有 2 個 Server,組成 HA 模式,在 Server 啟動的時候,往 ZooKeeper 寫入一個約定好的路徑下臨時節點,由於 ZooKeeper 只允許 1 個寫成功,誰先寫成功,誰就作為 Active, 並且由 ZooKeeper 通知到叢集中其他節點,其他節點則狀態改成 standby 狀態。

當 Active 節點宕機的時候,ZooKeeper 將節點狀態通知下去,其他的 standby 節點立刻往該節點裡面寫資料,寫成功了,就接替成為 Active。

整個流程大概就是這樣,這裡要注意一個點,就是在網路異常情況下,主備節點切換不那麼實時,可能會出現腦裂,也就是存在 2 個主節點的情況,這種情況的話,可以客戶端在切換的時候,可以嘗試等一等,狀態穩定之後,再切換。

5.png

自研系統的分散式協調場景

在自研分散式系統的時候,必然會遇到許多分散式協調的問題,ZooKeeper 就像一個萬能的工具箱。

針對不同的場景,基於 ZooKeeper 的特性,都能組合成一個解決方案;在寫分散式系統的時候,經常需要用到的有這幾個功能:

  • Master 的選舉

我們的系統需要選舉出來 1 個 Maseter 來執行任務;例如 ScheduleX 就是利用 ZooKeeper 做到這個的,Schedulex 的 Worker 節點有非常多,一些任務是非冪等的,只能由一個程序執行,這時候就需要從眾多的 Worker 中選一個 master 來,實現的方式主要有 2 種:

  • 搶佔主節點的方式:約定一個固定的路徑,誰往裡面寫臨時節點資料寫成功了,就算當 master,當 Master 宕機後,臨時節點會過期釋放,ZooKeeper 通知到其他節點,其他節點再繼續往裡面寫資料搶佔。

  • 最小節點方式:利用的是 ZooKeeper 的臨時有序節點實現的,如圖所示:要進行選主的時候,每臺 Server 往目錄下面寫一個臨時有序節點,約定好,序號最小的節點作為 master 即可。

6.png

  • 分散式鎖

在分散式環境中,程式都分佈獨立的節點中,分散式鎖是控制分散式系統之間同步訪問共享資源的一種方式,下面介紹下 Zookeeper 如何實現分散式鎖,分散式鎖主要有 2 種類型:

1、排他鎖(Exclusive Locks):稱為獨佔鎖,獲取到這個鎖後,其他的程序都不允許讀寫

實現的原理也很簡單,利用 ZooKeeper 一個具體路徑下只能建立一個節點的特性,約定誰建立成功了,就搶到了鎖,同時其他節點要監聽這個變化,臨時節點刪除了,可以被通知到去搶(Create),這個和 Master 選舉裡面搶佔 Master 節點,是一樣的做法:

7.png

2、共享鎖(Shared Locks):又稱為讀鎖,多個程序可以同時獲取這把鎖,進行讀操作,但是如果要寫操作,必須沒有讀操作了,且自己是第一個獲取到寫操作型別鎖的

實現的方式如圖示;讀的時候,建立一個 R 的臨時順序節點,如果比他小的節點裡面沒有 W 節點,那麼寫入成功,可以讀,如果要寫,則判斷所有 R 的節點中,自己是否最小的即可。

8.png

  • 分散式佇列

分散式佇列最常見的 FIFO(First Input First Output )先入先出佇列模型,先進入佇列的請求操作先完成後,才會開始處理後面的請求:

9.png

Zookeeper 實現 FIFO 佇列,和共享鎖實現類似,類似於一個全寫的共享鎖模型:

1、獲取/Queue 節點下的所有子節點,獲取佇列中的所有元素

2、確定自己的節點序號在所有子節點中的順序

3、如果自己的序號不是最小,那麼就需要等待,同時向比自己序號小的最後一個節點註冊 Watcher 監聽

4、接收到 Watcher 通知後,重複第一個步驟

  • 配置中心

使用 ZooKeeper 作為配置中心,利用的也是 ZooKeeper 的註冊/訂閱模式,這裡有個注意點,ZooKeeper 不適用於儲存太大的資料,一般不超過 1M,否則容易出現效能問題。

10.png

MSE 提供的 ZooKeeper 企業服務

MSE 和 ZooKeeper 的關係

微服務引擎(Micro Service Engine,簡稱 MSE)是一個面向業界主流開源微服務生態的一站式微服務平臺,微服務生態的所有服務都能夠在這個平臺上面被整合,它提供的引擎都是獨立託管的,目的就是為了給大家提供高效能、高可用、高整合、安全的服務,目前,MSE 提供瞭如下模組:

  • 註冊配置中心-(ZooKeeper/Nacos/Eureka)
  • 雲原生閘道器-(Envoy)
  • 分散式事務-(Seata)
  • 微服務治理(Dubbo/Spring Cloud/Sentinel/OpenSergo)

ZooKeeper 和 Nacos 一樣,提供註冊配置中心功能,但是 ZooKeeper 還提供了分散式協調的能力,應用在大資料領域。

MSE 提供的 ZooKeeper 企業服務分為基礎版和專業版兩種,前者適用於開發測試環境和簡單的生產環境,後者在效能、可觀測、高可用方便做了諸多提升,接下來,我們將介紹專業版,相比自建的優勢。

11.png

比自建的 ZooKeeper 更穩定和高可用

12.png

MSE 的產品架構圖

  • ZooKeeper 是多 AZ 部署的:大家知道 ZooKeeper 只有過半的節點才能選出主來,當一個 5 節點的 ZooKeeper 叢集,部署在 3 個可用區的時候,它應該要 2/2/1 的分佈,這樣的話,任意一個可用區出現故障,ZooKeeper 整體還是可用的,阿里雲 AZ 之間的延時,目前是低於 3ms 的,非常短是可控的。

  • 高可用負載均衡:使用者節點訪問 ZooKeeper 的 endpoint,是 MSE 提供的一個 SingleTunnelSLB,這個 SLB 是一個主備高可用的,它會自動對使用者請求做負載均衡,將請求壓力分散到後端節點,當後端節點故障時,會自動摘除,保證請求到正常的節點上面。

  • 節點故障自愈:依託於 K8s 的 Liveness 能力,在節點出現故障的時候,會自動恢復故障節點,及時的保障服務的可持續性。

  • 資料安全:專業版 ZooKeeper 提供了快照的備份能力,在叢集出現非預期的情況下 ,能夠快速重建恢復叢集中的資料,保障資料的安全。

上面介紹的是架構設計上面,對高可用的一個保障。

在研發過程,我們有一套完備的穩定性保障體系:從研發階段,到最後的變更上線,都有對應的規範制度,例如變更三板斧,在變更時,必須要滿足可觀測/可回滾/可灰度的情況下才能上線,否則會被打回;在執行時,我們有一系列的巡檢組建,配置一致性檢查,後面也會不斷的完善,巡檢出問題,立馬需要解決。

MSE 也把故障演練做到了常態化,針對常見的故障場景,例如網路中斷,CoreDNS 宕機、ECS 宕機等,都定期在跑著;在線上預警這塊,我們也做到了主動探測,及時發現,安排值班人員 24 小時處理,我們有一套 1/5/10 的應急流程,要求在 1 分鐘內發現問題,5 分鐘解決,10 分鐘恢復。

13.png

以上的這些,最終都是為了保障 MSE 的穩定高可用,MSE 線上最大規模的一個叢集,支援著 40w+的長連結,穩定運行了 3 年的時間,沒有出現過故障,SLA 達到 99.95%。

免運維,提供了豐富的控制檯功能

如果是自建 ZooKeeper 的話,需要做哪些事:

  • 搭建基礎設施:把一些基礎的設施給準備齊全,例如 ECS/SLB 等,再做網路規劃。

  • 安裝 ZooKeeper:安裝過程中,要配置很多引數,並對這些引數足夠的熟悉,否則出問題就抓瞎了,不同的引數,對叢集執行時的效能也是有一定影響的,這都需要要有足夠的專業知識,才能勝任。

  • 擴縮容:規劃 MyId 的分配,新擴容機器需要自增,否則新機器將無法加入舊叢集同步資料,因為只有 MyId 大的才會去主動連小的去同步叢集資料;新節點加入叢集,也是有嚴格的啟動順序的,新加入的機器數,必須小於原叢集的一半,否則會出現 master 選在新節點上面,導致資料丟失;在加入節點特別多的時候,需要按這個規則重複多次,少一個步驟,都很容易導致叢集選主失敗,資料丟失,造成線上生產故障。

  • 服務端配置變更:zoo.cfg 中的配置項,更新之後,需要把叢集中每臺機器手動重啟,才能觸發生效。

  • 資料管理:開源的 ZooKeeper 沒有圖形化管理工具,要檢視資料,得通過 zkClient 或者寫程式碼查詢,操作非常的複雜和繁瑣,這些都是自建帶來的問題。

  • 線上故障處理:例如 ZooKeeper GC 了,或者網路閃斷了,這時候就需要熟悉 ZK/JVM/作業系統的專業運維人員處理了。

而 MSE 提供的 ZooKeeper 企業服務,則將以上問題通過產品化的方式解決了:

14.png

15.png

需要一個 ZooKeeper 叢集的時候,一鍵購買,3 分鐘開箱即用,出現容量問題時,一鍵平滑擴縮容,還提供了重置資料、引數白屏化設定等功能,在可觀測這塊,也提供了常用的核心預設指標大盤,與之相配套的就是報警了。使用 ZooKeeper 企業服務,省心、省力,提高企業 IT ROI。

可觀測性增強

ZooKeeper 專業版的第三個優勢,可觀測性的增強:

  • 豐富的監控大盤:這次專業版和普羅米修斯進行了深度整合,並且給大家免費開啟使用,提供了 20 多個 Zookeeper 常用的監控指標,4 個核心資源監控指標

  • 支援核心告警規則:基本能滿足大家日常的運維需求了,當然,如果你還需要的話,可以隨時找我們,給你安排上

  • 開放豐富 Metrics 標準指標:這次專業版把 ZooKeeper 內建的 70 多個 Metrics 指標,都通過 API 的形式開放出去了,對應你們來講,就能夠利用這些資料,自己去繪製監控大盤了,非常的方便

16.png

效能提升

寫入效能優化提升 20%,資料可靠性達 99.9999999%(即 9 個 9)。

ZooKeeper 的寫入效能, 和磁碟效能有很大的關係,必須要把資料寫入到磁碟的事務日誌成功後,才算寫成功,為了提升寫效能,我們採用了阿里雲 ESSD 高效能雲盤,最大 IOPS 能夠達到 5W,最大吞吐量 350M/S,資料的可靠性 99.9999999%(即 9 個 9),整個寫入 TPS 效能能夠提升約 20%。

基於 Dragonwell 進行構建,讀取效能提升 1 倍

我們集成了阿里高效能 JDK,開啟了裡面的協程優化能力,並對 ZooKeeper 的讀寫任務佇列做了鎖力度的優化,在高併發處理的場景下,讀效能相比開源能夠提升 1 倍左右的效能。\

17.png

GC 時間降低 80%,大幅減少 Full GC 的情況

ZooKeeper 是時延敏感型的應用,GC 的時間和次數,會影響 ZooKeeper 的處理吞吐量,因此我們針對這種情況,做了 JVM 引數的調優,堆的設定根據不同的配置動態設定,同時提前做了資源碎片的回收,避免出現 FullGC,整體優化下來,GC 時間降低 80%,同時儘可能的避免了 FullGC。

18.png

基於 MSE,構建 Dubbo+Zookeeper 微服務

操作之前,需要購買一個 ZooKeeper,可以選擇按量付費,不需要是可以釋放,如果長期使用,可以選擇包年包月:

19.png

在選擇網路訪問方式的時候,以下幾種情況:

1、如果你只是使用 VPC 網路使用,你就選擇專有網路,選上交換機和專業網路,其他不用動(這裡注意:不要去選擇公網頻寬)

20.png

2、如果你只是要公網訪問,選擇公網網路,再選上對應的頻寬即可;

21.png

3、如果需要公網,同時也需要 VPC 網路訪問,那麼你選擇專有網路,同時在公網頻寬處,選擇你需要的公網頻寬,這樣就會建立 2 個接入點了;

22.png

購買之後,大概 5 分鐘左右,ZooKeeper 叢集就建立成功了,大家記住訪問方式, 等會 Dubbo 配置檔案裡面需要配置這個地址:

23.png

環境準備好了,就準備 Provider/Consumer 的配置了。欲瞭解詳細的操作步驟,可觀看直播影片進行了解:https://yqh.aliyun.com/live/detail/28603

寫在最後

MSE 提供的 ZooKeeper 企業服務,旨在為使用者提供更可靠的、成本更低、效率更高的,完全相容開源的分散式協調服務。提供後付費和包年包月兩類付費模式,支援杭州,上海,北京,深圳等海內外 23 個 region,滿足 95%地域使用者。如果你有其他新開服需要,可以聯絡我們。

現在購買 MSE 專業版 ZooKeeper,立享 9 折優惠,新老同享。

也可釘釘搜尋群號 34754806 可加入使用者群交流、答疑。

24.png

點選此處,前往 MSE 官網進行搶購吧!