歡迎光臨
每天分享高質量文章

【剖析 | SOFARPC 框架】系列之 SOFARPC 資料透傳剖析

SOFA

Scalable Open Financial Architecture

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


本文為《剖析 | SOFARPC 框架》第八篇,作者水寒,目前就職於網易

《剖析 | SOFARPC 框架》系列由 SOFA 團隊和原始碼愛好者們出品,

專案代號:,官方目錄目前已經全部認領完畢,文末提供了已完成的文章目錄。


  前言

《剖析 | SOFARPC 框架》系列之前的文章中,我們已經介紹了同步,異步,泛化呼叫等,也介紹了鏈路追蹤的能力。


本篇,我們將介紹一下 SOFARPC 中另一種內置的資料透傳的能力。依次介紹,資料透傳的概念, SOFARPC 的設計原理,以及各種不同呼叫方式下的透傳使用和詳細說明,最後, 還會比較一下和 SOFATracer 的區別。歡迎大家與我們討論交流。

  資料透傳介紹

首先,我們知道,在 RPC 呼叫中,資料的傳遞,是通過接口方法引數來傳遞的,需要接口方定義好一些引數允許傳遞才可以。在一些場景下,我們希望,能夠更通用的傳遞一些引數,比如一些標識性的信息。業務方可能希望,在每一次呼叫請求中都能夠傳遞一些自定義的信息到下游。甚至也希望下游能夠將一些資料傳遞迴來。


而資料透傳功能,就是指資料不需要以作為方法引數的形式在呼叫鏈路中進行傳遞,而是直接儲存到呼叫背景關係中,之後通過 RPC 的內置物件,進行傳遞,呼叫雙端可從背景關係中獲取資料而不需要去關註資料的傳輸過程。SOFARPC 提供的資料透傳支持請求資料透傳(客戶端向服務端)和響應資料透傳(服務端向客戶端)

  SOFARPC 設計原理

這裡主要是介紹一下,實現的核心原理,更加具體的每種呼叫方式的透傳,在後文中都會詳細介紹。


  • 用戶通過 SOFARPC 提供的 API 進行資料傳遞設置

  • SOFARPC 在呼叫傳輸前,將透傳的資料進行打包獲取

  • 進行正常的序列化和反序列化

  • SOFARPC 在反序列化時將用戶設置的透傳資料寫回 Context

  • 服務端用戶即可進行獲取使用

  不同呼叫方式的透傳

我們知道,SOFARPC 目前支持四種呼叫樣式,如果沒有閱讀過之前文章的同學,可以閱讀一下 SOFARPC 同步異步實現剖析 四種呼叫樣式下,請求透傳資料的原理都是一樣的,服務端設置響應透傳資料的原理也是一樣的,只是客戶端獲取響應透傳資料的方式有所不同(後三種樣式只介紹客戶端獲取響應透傳資料的原理)。


因此我們會介紹下不同呼叫方式的透傳細節,並介紹其使用方式,方便大家理解。以下為了方便說明,我們會使用如下的接口示例

接口服務

public interface HelloService {    String sayHello(String string); }

服務實現

public class HelloServiceImpl implements HelloService {    @Override    public String sayHello(String string) {        // 獲取請求透傳資料並打印        System.out.println("service receive reqBag -> " + RpcInvokeContext.getContext().getRequestBaggage("req_bag"));        // 設置響應透傳資料到當前執行緒的背景關係中        RpcInvokeContext.getContext().putResponseBaggage("resp_bag", "s2c");        return "hello " + string + " !";    } }


後續的所有呼叫樣式都使用HelloServiceImpl這個服務實現。(示例代碼在 SOFARPC 的測試 case 中都要對應的示例,大家可以對應閱讀)

對用戶可見的操作 API 只有一個就是 RpcInvokeContext,在 SOFABoot 和 SOFARPC 下都適用,當然如果你瞭解 SOFARPC 的 Filter 機制,也可以通過擴展這個來實現。

一、sync 呼叫下的透傳

使用示例

原理剖析

請求透傳資料

  1. 客戶端首先在 main 執行緒(圖中的user thread)中設置請求透傳資料到其呼叫背景關係RpcInvokeContext.requestBaggage屬性中,之後在呼叫過程中從requestBaggage中取出請求透傳資料並設置到SofaRequest.requestProps屬性中。

  2. 服務端接收到請求SofaRequest物件後,在其呼叫鏈中的 ProviderBaggageFilter#invoke 方法中會先從SofaRequest.requestProps中取出請求透傳資料並設置到當前服務端執行緒的呼叫背景關係RpcInvokeContext.requestBaggage屬性中,最後業務代碼就可以從呼叫背景關係中獲取請求透傳資料了。

響應透傳資料

  1. 服務端設置響應透傳資料到其呼叫背景關係RpcInvokeContext.responseBaggage屬性中,之後在ProviderBaggageFilter#invoke 方法中先從responseBaggage中取出響應透傳資料並設置到SofaResponse.responseProps屬性中。

  2. 客戶端main執行緒被喚醒後,先從SofaResponse.responseProps中獲取響應透傳資料,之後將響應透傳資料設置到其呼叫背景關係RpcInvokeContext.responseBaggage中,最後業務代碼就可以從呼叫背景關係中獲取響應透傳資料了。

二、oneway 呼叫下的透傳

使用示例

原理剖析


在 oneway 樣式下,客戶端不接受服務端響應,也不會獲取響應透傳資料。

三、future 呼叫下的透傳

使用示例

原理剖析

客戶端獲取響應透傳資料

future 樣式在 SOFARPC 內部會被轉化為 callback 的方式進行呼叫,在 callback 物件中會儲存main執行緒的呼叫背景關係;當客戶端接收到響應時,會執行該 callback 物件的回呼函式,在其回呼函式中,對於響應透傳資料,會做如下操作:


  1. SofaResponse.responseProps中獲取響應透傳資料

  2. 從 callback 物件中獲取 main 執行緒的呼叫背景關係

  3. 設置響應透傳資料到 main 執行緒的呼叫背景關係

  4. 將 main 執行緒背景關係拷貝到當前的回呼執行緒中


實際上,第三步與第四步在 SOFARPC 原始碼中順序相反,本文這樣解讀是為了更容易理解。這樣無論是 future 樣式(從 main 執行緒的呼叫背景關係獲取響應透傳資料)還是 callback 樣式(從回呼執行緒的呼叫背景關係獲取響應透傳資料),都可以順利的獲取到響應透傳資料。

四、callback 呼叫下的透傳

使用示例

原理剖析


與future樣式原理一樣,只是最終業務代碼中是從回呼執行緒而不是main執行緒的呼叫背景關係中獲取響應透傳資料。

  與 SOFATracer 的比較

如果瞭解過 SOFATracer 的同學會有疑問,這個跟 Tracer 是不是有功能上的重疊呢?實際上 SOFATracer 是螞蟻開源的一個分佈式鏈路追蹤系統,SOFARPC 目前已經和 Tracer 做了集成,預設開啟。


和 Tracer 進行資料傳遞不同的是

  • SOFARPC 的資料透傳更偏向業務使用,而且可以在全鏈路中進行雙向傳遞,呼叫方可以傳給服務方(請求透傳資料),服務方也可以傳遞信息給呼叫方(響應透傳資料),SOFATracer 更加偏向於中間件和業務無感知的資料的傳遞,並且只能進行單向傳遞。也就是向下傳遞,呼叫方並不能獲取服務提供方的透傳資料。

  • SOFARPC 的透傳可以選擇性地不在全鏈路中透傳(主動清除呼叫背景關係資料),而 Tracer 中如果傳遞大量信息,會在整個鏈路中傳遞。可能對下游業務會有影響。


所以整體來看,兩種方式各有利弊,在有一些和業務相關的透傳資料的情況下,可以選擇 SOFARPC 的透傳。

  《剖析 | SOFARPC 框架》系列歷史文章

長按關註,獲取分佈式架構乾貨

歡迎大家共同打造 SOFAStack https://github.com/alipay



赞(0)

分享創造快樂