服務框架的幾種服務調用形式

1. 同步調用

同步服務調用是最經常使用的一種服務調用方式,它的工做原理和使用都很是簡單,分佈式服務框架默認都須要支持這種調用形式。緩存

它的工做原理以下:客戶端發起遠程服務調用請求,用戶線程完成消息序列化以後,將消息投遞到通訊框架,而後同步阻塞,等待通訊線程發送請求並接收到應答以後,喚醒同步等待的用戶線程,用戶線程獲取到應答以後返回。服務器

它的工做原理圖如圖:網絡

  1. 消費者調用服務端發佈的接口,接口調用由分佈式服務框架包裝成動態代理,發起遠程服務調用。
  2. 消費者線程調用通訊框架的消息發送接口以後,直接或者間接調用 wait()方法,同步阻塞等待應答。
  3. 通訊框架的 I/O線程經過網絡將請求消息發送給服務端。
  4. 服務端返回應答消息給消費者,由通訊框架負責應答消息的反序列化。 
  5. I/O線程獲取到應答消息以後,根據消息上下文找到以前同步阻塞的業務線程, notify()阻塞的業務線程,返回應答給消費者,完成服務調用。

爲了防止服務端長時間不返回應答消息致使客戶端用戶線程被掛死,用戶線程等待的時候須要設置超時時間,這個超時時間與服務端或者客戶端配置的超時時間對應。框架

2. 異步服務調用

基於 JDK的 Future機制,能夠很是方便地實現異步服務調用。 在實際項目中,每每會擴展 JDK的 Future,提供 Future-Listener機制,它支持主動獲取和被動異步回調通知兩種模式,適用於不一樣的業務場景。
在實際項目中,每每會擴展 JDK的 Future,提供 Future-Listener機制,它支持主動獲取和被動異步回調通知兩種模式,適用於不一樣的業務場景。異步

2.1 添加Listener的異步服務調用

異步服務調用的工做原理如圖 :分佈式

                

異步服務調用的工做流程以下:
1)消費者調用服務端發佈的接口,接口調用由分佈式服務框架包裝成動態代理,發起遠程服務調用。
2)通訊框架異步發送請求消息,若是沒有發生 I/O異常,返回。
3)請求消息發送成功後, I/O線程構造 Future對象,設置到 RPC上下文中。
4)用戶線程經過 RPC上下文獲取 Future對象。
5)構造 Listener對象,將其添加到 Future中,用於服務端應答異步回調通知。
6)用戶線程返回,不阻塞等待應答。
7)服務端返回應答消息,通訊框架負責反序列化等。性能

8)I/O線程將應答設置到 Future對象的操做結果中。
9)Future對象掃描註冊的監聽器列表,循環調用監聽器的operationComplete方法,將結果通知給監聽器,監聽器獲取到結果以後,繼續後續業務邏輯的執行,異步服務調用結束。測試

2.2 無Listener的異步服務調用

另一種異步服務調用形式,就是不添加 Listener,用戶連續發起 N次服務調用,而後依次從 RPC上下文中獲取 Future對象,最終再主動 get結果,業務線程阻塞,相比於老的同步服務調用,它的阻塞時間更短,其工做原理如圖。
                優化

2.3 異步服務調用的優勢

  1. 化串行爲並行,提高服務調用效率,減小業務線程阻塞時間。
  2. 化同步爲異步,避免業務線程阻塞。

串行到並行的優化原理如圖:因爲每次服務調用都是同步阻塞,三個服務調用總耗時爲T = T1 + T2 + T3spa

            

採用異步服務調用以後的優化效果,如圖:
                

採用異步服務調用模式,最後調用三個服務異步操做結果 Future的 get方法同步等待應答,它的總執行時間 T = Max(T1, T2, T3),相比於同步服務調用,性能提高效果很是明顯。

3. 並行服務調用

串行服務調用比較簡單,但在一些業務場景中,須要採用並行服務調用來下降 E2E的時延:

  1. 多個服務之間邏輯上不存在互相依賴關係,執行前後順序沒有嚴格的要求,邏輯上能夠被並行執行。
  2. 長流程業務,調用多個服務,對時延比較敏感,其中有部分服務邏輯上無上下文關聯,能夠被並行調用。

並行服務調用的目標主要有兩個:
1)下降業務 E2E時延。
2)提高整個系統的吞吐量。咱們以手遊購買道具流程爲例,對並行服務調用進行說明,如圖。

            

實現並行服務調用的幾種技術方案:

  1. JDK 7的 Fork/Join,能夠實現子任務的並行執行和結果匯聚(推薦)
  2. BPM的 Parallel Gateway
  3. 批量串行服務調用

關於批量串行服務調用的流程以下:

               

1)服務框架提供批量服務調用接口供消費者使用,它的定義樣例以下:

2)平臺的並行服務調用器建立並行 Future,緩存批量服務調用上下文信息。
3)並行服務調用器循環調用普通的 Invoker,經過循環的方式執行單個服務調用,獲取到單個服務的 Future以後設置到 Parallel Future中。
4)返回 Parallel Future給消費者。
5)普通 Invoker調用通訊框架的消息發送接口,發起遠程服務調用。
6)服務端返回應答,通訊框架對報文作反序列化,轉換成業務對象更新 Parallel Future的結果列表。
7)消費者調用 Parallel Future的 get(timeout)方法, 同步阻塞,等待全部結果所有返回。
8) Parallel Future經過對結果集進行判斷,看全部服務調用是否都已經完成(包括成功、失敗和異常)。
9)全部批量服務調用結果都已經返回, Notify消費者線程,消費者獲取到結果列表,完成批量服務調用,流程繼續執行。

經過批量服務調用 + Future機制,咱們實現了並行服務調用,並且沒有建立新的線程,用戶不用擔憂依賴線程上下文的功能出異常。

4. 泛化調用

泛化調用一般包含兩種模式:泛化引用和泛化實現。泛化引用主要用於客戶端沒有 API接口及數據模型的場景,參數及返回值中的全部 POJO均用 Map表示,一般用於框架集成,好比實現一個通用的服務測試框架。泛化實現主要用於服務器端沒有 API接口及數據模型的場景,參數及返回值中的全部 POJO均用 Map表示,一般用於框架集成,好比實現一個通用的遠程服務Mock框架。泛化調用的設計要點以下。
1)分佈式服務框架提供泛化接口,供服務提供者實現和消費者引用,它的參考定義以下:

2)消費者若是引用泛化接口,則直接將請求參數轉換成 Map,應答消息也自動轉換成 Map。 3)服務提供者若是使用泛化實現發佈服務,則自動將請求參數轉換成 Map,調用GenService的泛化實現類,應答消息自動包裝成 Map返回。 泛化調用因爲比較靈活,沒有服務契約,所以在實際項目中慎用,它一般用於測試集成、系統上線以後的回聲測試等。

相關文章
相關標籤/搜索