天天看點

螞蟻金服通信架構SOFABolt解析 | 協定架構解析

SOFA

Scalable Open Financial Architecture

是螞蟻金服自主研發的金融級分布式中間件,包含了建構金融級雲原生架構所需的各個元件,是在金融場景裡錘煉出來的最佳實踐。

本文為《螞蟻金服通信架構 SOFABolt 解析》系列第三篇,作者顔洄、丞一。

《螞蟻金服通信架構 SOFABolt 解析》系列由 SOFA 團隊和源碼愛好者們出品。

SOFARPC: https://github.com/alipay/sofa-rpc SOFABolt: https://github.com/alipay/sofa-bolt
螞蟻金服通信架構SOFABolt解析 | 協定架構解析

前言

為了讓中間件開發者們将更多的精力投入到産品的功能特性上,而不是重複的寫通信層架構,螞蟻中間件團隊設計并實作了 SOFABolt。

Bolt 名字取自迪士尼動畫-閃電狗,是一個基于 Netty 最佳實踐的輕量、易用、高性能、易擴充的通信架構。螞蟻中間件的同學這些年在微服務和消息中間件上解決了很多網絡通信的問題,積累了很多經驗,并将這些經驗、解決方案沉澱到了 SOFABolt 這個項目中,希望能讓更多需要使用網絡通信的團隊、開發者受益。目前 SOFABolt 已經運作在滿意中間件的微服務 (SOFARPC)、消息中心、分布式事務、分布式開關、以及配置中心等衆多産品上。

主要特性

SOFABolt 核心功能包括三大塊:

  • 網絡通信能力
  • 協定架構
  • 私有協定實作

網絡通信能力(remoting-core)可以了解為 Netty 的最佳實踐,并額外進行了一些優化工作,包含:

  • 基于 Netty 的高效的網絡IO于線程模型的應用
  • 連結管理(無鎖建連、定時斷連、自動重連)
  • 通信模型(oneway、sync、callback、future)
  • 逾時控制
  • 批量解包和批量送出處理
  • 心跳于IDLE機制

協定架構(protocol-skeleton)包含指令處理器、編解碼器等,是底層通信能力之上,具體私有協定之下,連接配接通信能力和私有協定的中間層。網絡通信層是 SOFABolt 對 Netty 的封裝和功能增強,協定架構則是 SOFABolt 對網絡請求處理流程的抽象,是使用者可以不關心底層細節快速實作自己的處理器來完成網絡請求的處理邏輯,是使用者可以進行拓展來實作自定義的私有協定的基礎,也是本篇文章分析的内容。

由于性能、安全性等等的原因,很多中間件都會采用私有協定進行通信。SOFABolt 除了提供基礎的通信能力、協定架構之外,還提供了預設的 RPC 協定的實作,這樣它就是一個完整的通信架構,使用者可以不關心協定而直接上手使用。本篇文章主要分析 SOFABolt 的協定架構的設計和實作,不展開對 SOFABolt 中的RPC 協定實作做介紹。

協定架構整體如下:

螞蟻金服通信架構SOFABolt解析 | 協定架構解析
  • Command:協定指令,通訊資料的頂層抽象。從互動的角度可以分為Request(請求)于Response(響應),從功能的角度,分為負載指令(交換業務資料)和控制指令(進行系統的管理、協調等)。
  • CommandEncoder/CommandDecoder:協定指令的編解碼器,自定義協定實作的基礎,編解碼器完成對象和位元組數組之間的互相轉換。
  • CommandHandler:協定指令的處理器,指令處理入口,負責分發、處理指令。
  • CommandFactory:協定指令工廠類,負責建立協定指令對象。
  • HeartbeatTrigger:心跳的處理器,使用者使用者拓展特定的心跳機制的處理。

    下面以 SOFABolt 中預設實作的 RPC 協定為例來介紹 SOFABolt 協定架構的實作。

3.1 請求的處理流程

一個請求處理流程大緻如下:

通過 CommandFactory 建構請求對象

通過 CommandEncoder 對請求對象進行編碼,寫入到網絡連接配接

服務端從連接配接中讀取資料,通過 CommandDecoder 解析成請求對象

CommandHandler 接收請求對象,進行分發和處理

螞蟻金服通信架構SOFABolt解析 | 協定架構解析

CommandFactory 是一個工廠類,比較簡單,不展開介紹。編解碼相關内容見《SOFABolt編解碼機制》。下面介紹一下CommandHandler 對請求的分發和處理。

螞蟻金服通信架構SOFABolt解析 | 協定架構解析

上面是 SOFABolt 中 RpcHandler 的代碼片段,這段代碼是指令處理的入口:

首先從連接配接的上下文中擷取使用的協定的版本 ProtocolCode

再根據 ProtocolCode 從 ProtocolManager 中擷取具體的協定

之後從協定中擷取 CommandHandler,并構造請求的上下文資訊和請求的對象(代碼片段中的msg)送出處理

上面的處理邏輯中透露出一個資訊:SOFABolt 支援同時運作多個版本的協定,通過 ProtocolCode 來區分協定。這一點可以使得系統在做更新或重構時,需要同時支援新老系統不同協定時變得簡單。

螞蟻金服通信架構SOFABolt解析 | 協定架構解析

上面是 CommandHandler 的代碼片段,透露出的資訊是 SOFABolt 支援批量送出請求,這在《SOFABolt 編解碼機制》一文中也有部分介紹。而具體的 process流程如下:

螞蟻金服通信架構SOFABolt解析 | 協定架構解析

通過 Command 對象擷取 CommandCode,根據 CommandCode 擷取對應的RemotingProcessor 進行處理。

CommandCode是一個接口,隻有一個傳回 short 的value() 方法,表示Command的具體類型,每個請求都需要有自己的 CommandCode 來辨別自己的類型。架構通過一個 Map 來維護 CommandCode 和 RemotingProcessor 的關系,每個 CommandCode 需要有對應的 RemotingProcessor 進行處理,一個 RemotingProcessor 可以處理多個 CommandCode 的請求。

螞蟻金服通信架構SOFABolt解析 | 協定架構解析

再往下看一層,請求會被送出到RemotingProcessor中處理。上面是RpcRequestProcessor 處理請求的代碼片段,處理流程中會通過cmd.getRequestClass()來擷取請求的對象的 Class 名稱,再擷取對應的UserProcess進行處理(具體處理不再上面的代碼片段中)。

對使用者來說,隻需要實作自己的 Command 對象、實作自己的 UserProcessor 并注冊到 ProcessorManager 中,就可以完成自己的網絡通信。

以上是一個請求在 SOFABolt 的協定架構下的處理流程和核心代碼的分析。

3.2 協定架構的拓展機制

通過對請求處理流程的分析可以感受到 SOFABolt 的協定架構是支援多協定版本運作,能直接使用,也支援進行拓展來實作更豐富和定制化的功能。下面具體介紹SOFABolt 的拓展機制。

螞蟻金服通信架構SOFABolt解析 | 協定架構解析

上圖是 RemotingCommand 在處理過程中的路由示意圖。第一層路由根據 ProtocolCode 進行,第二層路由根據 CmdCode 進行,第三層路由則根據 RequestClass 進行。使用者可以在每一層進行擴充來實作自己的處理。

這種設計具有很好的拓展性和靈活性,ProtocolCode 用于區分“大版本”的協定,适用于協定發生較大的變化的場景。CmdCode 則辨別請求類型,比如在RPC場景中 CmdCode 可能就兩個:RPC_REQUEST、RPC_RESPONSE,而在消息場景中CmdCode 可能會更豐富一些,比如有發送消息、批量發送消息、投遞消息等等。RequestClass 是 Command上承載的資料的類型,使用者根據不同的類名進行不同的業務邏輯的實行。

實際應用中,以 RPC 的場景為例,使用者更多的是去實作 UserProcessor 來完成不同的業務邏輯的處理。而在消息的場景中,因為消息承載的是二進制的資料,是以請求的資料類型是固定的,系統更多的是拓展 CmdCode 來執行不同類型的請求的處理,比如心跳請求的處理、寫入消息的處理、批量寫入消息的處理等等。SOFABolt 協定架構的設計和實作,具備較好的可拓展性,使其能應用于螞蟻的 RPC架構、消息中心、分布式開關、配置中心等多個中間件。

3.3 使用 SOFABolt 自定義協定

在了解了SOFABolt協定架構的基礎結構、請求處理流程、拓展機制後,我們來嘗試分析如何使用SOFABolt以更深入的了解它的協定架構。

下面以應用到 RPC 架構中為例進行分析。使用 SOFABolt 的第一步就是實作自己需要的 Command。因為 SOFABolt 中已經包含了預設的 RPC 協定的實作,是以在RPC 的場景中,并不需要拓展 Command 類。

螞蟻金服通信架構SOFABolt解析 | 協定架構解析

SOFABolt 中也提供了CommandFactory 的預設實作:RpcCommandFactory,是以這塊也不需要進行拓展。

螞蟻金服通信架構SOFABolt解析 | 協定架構解析

同樣的,SOFABolt中也包含了CommandEncoder和CommandDecoder 的實作,是以對于一個 RPC 應用而言,唯一需要拓展實作的就是在服務端注冊自己的UserProcessor:RpcServer#registerUserProcessor(UserProcessor)。

螞蟻金服通信架構SOFABolt解析 | 協定架構解析

上面是 UserProcessor 相關的類圖,主要分兩類:注冊到單一資料類型上的 UserProcessor 和支援注冊到多個類型的 MultiInterestUserProcessor。

MultiInterestUserProcessor在 UserProcessor 的基礎上增加了multiInterest()方法,架構将此 Processor 注冊到 multiInterest() 方法傳回的多個資料類型上,這樣便于一個 Processor 處理多種資料類型的請求的場景。

使用者隻需要根據自己的需求,選擇是否使用 MultiInterestUserProcessor。再進一步根據是否需要同步處理來選擇繼承 Sync 或者 Async 的 UserProcessor 子類即可。那麼對于一個RPC的使用場景來說,實作 UserProcessor 并注冊到 RpcServer 和RpcClient即是所有的開發工作。

總結

本文首先對 SOFABolt 做了簡要的介紹,之後介紹了 SOFABolt 協定架構的整體結構、Command 的處理流程、拓展機制,之後通過分析如何使用 SOFABolt 來加深對 SOFABolt 協定架構及其拓展性的了解。