Facebook「配置大規模伺服器」的兵刃:位置感知分發
Facebook的基礎設施包括許多地域分散的數據中心,它們託管運行數百萬台伺服器。這些伺服器運行眾多系統,從前端Web伺服器、新聞源(News Feed)聚合系統到消息傳遞和實時視頻應用,不一而足。除了常規的代碼推送外,我們還每天將千上萬的配置變更發送到伺服器。因此,我們的伺服器執行數萬億次配置檢查相當普遍。配置檢查的一個例子是,為一個用戶顯示英語文本,為另一個用戶顯示葡萄牙語文本,確保Web伺服器對用戶體驗實現個性化。
我們在本文中描述了位置感知分發(LAD),這個新的點對點(P2P)系統處理將配置變更分發到數百萬台伺服器的任務。我們發現,LAD在分發大型更新時出色得多,LAD可分發100 MB,之前只能分發5 MB;還靈活擴展,每個分發器可以支持約40000個訂戶,之前支持2500個訂戶。
背景:我們在LAD之前如何分發配置?
我們在2015年的SOSP論文中曾描述(https://research.fb.com/publications/holistic-configuration-management-at-facebook/),Facebook的配置管理系統(名為Configerator)使用開源分散式同步服務ZooKeeper來分發配置更新。
ZooKeeper中的所有數據存儲在單個一致的數據存儲區中。每個ZooKeeper節點(znode)可能含有數據或其他子節點znode。可以使用分層路徑(比如/root/znode/my-node)來訪問每個znode。從ZooKeeper讀取數據的客戶端可以對znodes進行監視;更新znode時,ZooKeeper會通知那些客戶端,以便它們可以下載更新。
ZooKeeper強大的一致性和嚴格順序保證對於我們可以可靠地擴展和運行系統來說至關重要。然而,隨著基礎設施的規模擴大到數百萬台機器,我們發現ZooKeeper成了瓶頸。
嚴格順序保證:ZooKeeper的一項關鍵特性是,它提供嚴格順序保證,這意味著寫入始終由單個線程按順序處理。現在,為了確保讀取不至於等待時間過長,ZooKeeper使讀取處理和寫入處理交錯進行。我們發現,針對特定znode的更新可能會觸發大量監視,這反過來會觸發客戶端的大量讀取。幾個這樣的寫入可能導致停頓,從而阻礙更新。
驚群問題:更新數據znode時,ZooKeeper會通知所有對更新有興趣的客戶端。這可能會觸發驚群(thundering herd)問題,因為入站的客戶端請求讓ZooKeeper不堪重負。
大型更新會使網卡無力處理:我們的一些配置文件最大可達5 MB。鑒於網卡速率為10 Gbps,我們發現一個設備只能為約2000個客戶端提供服務。如果頻繁更新大文件,我們會發現更新可能需要10秒才能分發到所有有興趣的客戶端。
設計著眼未來的系統
我們開始設計新的分發系統時提出了幾個要求,包括如下:
支持大型更新:文件大小從5 MB增加到100 MB。
獨立的數據存儲區:ZooKeeper將數據存儲區與其分發框架結合起來。我們希望數據存儲和分發這兩部分分開來,那樣每個部分可以獨自選型和擴展。
分發容量:輕鬆支持數百萬客戶端。
延遲:將分發延遲限制在5秒以內。
配置文件:支持數量比之前基於ZooKeeper的系統多10倍的配置文件。
靈活應對驚群問題和更新速度激增的能力。
位置感知分發(LAD)簡介
LAD由兩個主要組件組成,它們通過Thrift RPC相互聯繫:
代理:在每個機器上運行的守護程序,負責將配置文件發送到任何有興趣的應用程序。
分發器:該組件負責兩個任務。首先,它輪詢數據存儲區,查找有無新的更新。其次,它為一組對更新有興趣的代理構建分發樹。
上圖顯示了LAD如何將代理組織到分發樹中,分發樹實際上是一個組織有序的點對點網路。如步驟1所示,代理代表在設備上運行的應用程序向分發器發送「訂閱」請求。分發器通過向父節點發送「添加peer」請求(步驟2),將代理添加到分發樹。一旦代理添加到了分發樹,它開始接收元數據(步驟3)更新。這些被過濾,代理響應內容請求(步驟4)。如果父節點含有內容,它會立即發送到子節點;不然,它會從父節點下載內容(步驟5)。
通過利用分發樹,LAD確保僅將更新發送到有興趣的代理,而不是發送到所有機器。此外,父節點機器可以將更新直接發送到子節點,這確保根(root)附近沒有哪個機器不堪重負。
我們之前使用ZooKeeper時的一個重要心得是,將元數據更新和分發與內容分發分開來。 LAD的架構依賴代理不斷接收元數據更新。如果每個代理都要接收所有元數據更新,請求量會太大。我們在LAD中通過使用分片(shard)解決了這個問題:我們不是依賴將整個數據樹作為一顆分發樹的一部分來提供,而是將它拆分成較小的分發樹,每顆小分發樹負責樹的某個部分。
我們實現分片設計的方法是,讓每個分片植根於目錄結構中的某個點,然後將所有對象都包括在其下面。分片為訂閱提供了一種便利的手段:它限制了分發樹的總數,同時均衡了每個代理收到的元數據數量。
控制和數據流
控制平面(上圖中的左側)是分發器與每個訂戶之間的輕量級Thrift RPC。分發器使用控制平面發送樹命令,樹命令向父節點告知新的子節點,並檢查訂戶的活躍度。訂戶也使用控制平面向分發器發送訂閱請求。分發器將這些請求映射到該訂閱所屬的分片,並將訂戶添加到分發樹中。
數據流平面(上圖中的右側)是Thrift RPC,位於分發樹中的peer之間,負責完成繁重任務。父節點使用數據流平台,將源自分發器的元數據更新發送到子節點。子節點也使用數據流平面向父節點請求它們感興趣的內容。
擁有獨立的控制平面和數據流平面使每個分發器能夠處理約40000個訂戶;ZooKeeper之前處理約2500個訂戶。
若干經驗
我們已在構建和部署LAD方面獲得了幾個寶貴的經驗。尤其是這幾點:
工具和監控對於生產部署至關重要。我們明白,由於不清楚在任何某個請求的發送或接收路徑中有哪些節點,基於P2P的系統運行和調試起來頗具挑戰性。
故障注入和災難準備測試在大規模環境下至關重要。除了詳細記錄的操作程序外,我們發現,運行測試、制定策略以便出現問題時積極有效地應對也很重要。具體來說,我們運行了一系列測試,有意引入了各種類型的應用程序、主機、網路和集群層面的故障,以驗證LAD的彈性,又不影響任何客戶端。這個做法頗有成效,因為我們不光發現了程序和工具方面的漏洞,還發現了代碼缺陷。
持續定期的測試對於確保系統長期可靠至關重要。上面列出的測試僅僅運行一次遠遠不夠,因為在Facebook節奏很快,系統或工具方面的觀點可能隨時有變。我們在使測試流程實現自動化,以便定期對故障做出響應。
LAD的下一步是什麼?
LAD目前作為我們配置管理系統的數據分發框架部署到生產環境中。我們還在評估是否可用於其他場合的大規模內容分發。


※螞蟻金服:金融級分散式中間件 SOFA 背後的故事
※又一個 AI 預測世界盃冠軍是「德國」
TAG:雲頭條 |