1. 程式人生 > >[從原始碼學設計]螞蟻金服SOFARegistry之網路封裝和操作

[從原始碼學設計]螞蟻金服SOFARegistry之網路封裝和操作

# [從原始碼學設計]螞蟻金服SOFARegistry之網路封裝和操作 [toc] ## 0x00 摘要 SOFARegistry 是螞蟻金服開源的一個生產級、高時效、高可用的服務註冊中心。 本系列文章重點在於分析設計和架構,即利用多篇文章,從多個角度反推總結 DataServer 或者 SOFARegistry 的實現機制和架構思路,讓大家藉以學習阿里如何設計。 本文為第二篇,介紹SOFARegistry的網路封裝和操作。 ## 0x01 業務領域 ### 1.1 SOFARegistry 總體架構 因為有的兄弟可能沒有讀過前面MetaServer的文章,所以這裡回憶下SOFARegistry 總體架構。 - **Client 層** 應用伺服器叢集。Client 層是應用層,每個應用系統通過依賴註冊中心相關的客戶端 jar 包,通過程式設計方式來使用服務註冊中心的服務釋出和服務訂閱能力。 - **Session 層** Session 伺服器叢集。顧名思義,Session 層是會話層,通過長連線和 Client 層的應用伺服器保持通訊,負責接收 Client 的服務釋出和服務訂閱請求。該層只在記憶體中儲存各個服務的釋出訂閱關係,對於具體的服務資訊,只在 Client 層和 Data 層之間透傳轉發。Session 層是無狀態的,可以隨著 Client 層應用規模的增長而擴容。 - **Data 層** 資料伺服器叢集。Data 層通過分片儲存的方式儲存著所用應用的服務註冊資料。資料按照 dataInfoId(每一份服務資料的唯一標識)進行一致性 Hash 分片,多副本備份,保證資料的高可用。下文的重點也在於隨著資料規模的增長,Data 層如何在不影響業務的前提下實現平滑的擴縮容。 - **Meta 層** 元資料伺服器叢集。這個叢集管轄的範圍是 Session 伺服器叢集和 Data 伺服器叢集的伺服器資訊,其角色就相當於 SOFARegistry 架構內部的服務註冊中心,只不過 SOFARegistry 作為服務註冊中心是服務於廣大應用服務層,而 Meta 叢集是服務於 SOFARegistry 內部的 Session 叢集和 Data 叢集,Meta 層能夠感知到 Session 節點和 Data 節點的變化,並通知叢集的其它節點。 ### 1.2 應用場景 DataServer,SessionServer,MetaServer 本質上都是網路應用程式。這就決定了網路封裝和操作是本系統的基礎模組及功能,下面我們講講其應用場景。 #### 1.2.1 單元化狀態 SOFARegistry 的應用場景是單元化狀態下。 在單元化狀態下,一個單元,是一個五臟俱全的縮小版整站,它是全能的,因為部署了所有應用;但它不是全量的,因為只能操作一部分資料。能夠單元化的系統,很容易在多機房中部署,因為可以輕易的把幾個單元部署在一個機房,而把另外幾個部署在其他機房。藉由在業務入口處設定一個流量調配器,可以調整業務流量在單元之間的比例。 #### 1.2.2 內網通訊 所以 SOFARegistry 考慮的就是在 IDC 私網環境中如何進行節點間通訊。高吞吐、高併發的通訊
,數量眾多的連線管理(C10K 問題),便捷的升級機制,相容性保障,靈活的執行緒池模型運用,細緻的異常處理與日誌埋點等,這些功能都需要在通訊協議和實現框架上做文章。 #### 1.2.3 Http協議 伺服器也有若干配置需求,這用簡單的http協議即可。 ### 1.3 問題點 在這種內網單元化場景下,能夠想到的問題點如下: - 如何制定私有協議。對於私網環境,如果所有應用的節點間,全部通過標準協議來通訊,會有很多問題:比如研發效率方面的影響,升級相容性,無用欄位的傳輸,功能定製也可能不那麼靈活。 - 如何進行連結管理(無鎖建連、定時斷連、自動重連); - 如何進行精細的執行緒模型的設計; - 如何進行超時控制; - 如何進行批量解包和批量提交處理; - 如何進行心跳控制; - 如何支援通訊模型(oneway、sync、callback、future); - 如何實現長連線; - 如何實現推拉模式; - 如何進行節點判活; ### 1.4 解決方案 對於這種高效能,高併發的場景,在Java體系下,必然選擇非阻塞IO複用,那麼自然選擇基於Netty進行開發。 ### 1.5 阿里方案 阿里就是藉助 [SOFABolt](https://github.com/sofastack/sofa-bolt) 通訊框架,實現基於TCP長連線的節點判活與推模式的變更推送,服務上下線通知時效性在秒級以內。 sofa-bolt是螞蟻開源的一款基於Netty的網路通訊框架。在Netty的基礎上對網路程式設計常見問題進行了一層簡單封裝,讓中介軟體開發者更關注於中介軟體產品本身。 大體功能為: 1. 連線管理 2. 請求處理 SOFABolt可以理解為Netty的最佳實踐,並額外進行了一些優化工作。 - 基於Netty的高效的網路IO於執行緒模型的應用 - 連結管理(無鎖建連、定時斷連、自動重連) - 通訊模型(oneway、sync、callback、future) - 超時控制 - 批量解包和批量提交處理 - 心跳於IDLE機制 SOFABolt框架我們後續可能會專門有系列進行分析,目前認為基於SOFABolt此可以滿足我們需求,所以我們會簡單介紹SOFABolt,重點在於如何使用以及業務實現
。 ### 1.6 實現問題 在確定了採用SOFABolt之後,之前提到的問題點就基本被SOFABolt解決了,所以我們暫時能想到的其他問題大致如下: - 對於網路中的各種功能模組,是否需要封裝,如果封裝,到什麼程度比較恰當; - 具體封裝,縱向橫向分別需要細化到什麼程度; - Data Server 既要對外提供服務,也會作為客戶端向其他模組傳送請求,這兩個功能是否需要抽象出來; - 是否需要按照具體業務功能進行分類封裝; ### 1.7 總述 我們提前劇透,即從邏輯上看,阿里提供了兩個層級的封裝 從連線角度看,阿里實現了基於 netty.channel.Channel 的封裝,從下往上看是: - 因為SOFABolt基於Netty,所以封裝的核心是netty.channel.Channel。 - 在此基礎上, SOFABolt封裝了com.alipay.remoting.Connection - 然後 SOFARegistry 基於SOFABolt 封裝了 BoltChannel 從應用角度看,阿里實現了Server,Client層次的封裝,從下往上看是: - SOFABolt構建了 RpcServer,RpcClient。 - SOFARegisty 基於 RpcServer,RpcClient 構建了BoltClient 和 BoltServer。 - 然後 SOFARegistry 基於此構建了 BoltExchange。作為 Client / Server 連線的抽象,負責節點之間的連線。 - 最後構建了 XXXNodeExchanger,在 BoltExchange 基礎上,把所有 Data Server 相關的 **非** “Server,Client概念 強相關”
的網路操作統一集中在這裡,使用者可以直接使用。以DataServer業務模組為例,其內部按照業務不同,實現了 DataNodeExchanger 和 MetaNodeExchanger。用以讓: - DataServer 內部直接使用 DataNodeExchanger 與其他 DataServer 互動, - DataServer 內部直接使用 MetaNodeExchanger 與 MetaServer 互動。 具體邏輯大致如下: ```java +---------------------+ +---------------------+ | | | | | DataNodeExchanger | | MetaNodeExchanger | | | | | +----------------+----+ +--------+------------+ | | +-----------+ +-------------+ | | v v +---------+---------------------+--------+ | BoltExchange | | +------------------------------------+ | | | | | | |