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

【剖析 | 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)

分享創造快樂