thrift調用流程分析

因爲工做須要使用thrift,而且須要根據需求修改thrift源碼,所以必須熟悉thrift執行的流程。如下是根據thrift源碼閱讀而得出流程分析。服務器

thrift協議棧概述

thrift是一個rpc框架,開發者能夠經過thrift自帶的接口定義語言(IDL)來自動生成客戶端和服務端的rpc代碼。
thrift協議棧以下圖所示:多線程

thrift架構

在client和server的最頂層都是用戶自定義的處理邏輯,也就是說用戶只須要編寫用戶邏輯,就能夠完成整套的rpc調用流程。用戶邏輯的下一層是thrift自動生成的代碼,這些代碼主要用於結構化數據的解析、發送和接收,同時服務端的自動生成代碼中還包含了rpc請求的轉發(client的A調用轉發到server A函數進行處理)。架構

從上面能夠看出thrift的模塊是分層設計的,在每個層次能夠根據業務的實際須要選擇合適的實現方式。併發

thrift主要分爲如下幾種層次模塊:框架

  • 底層io模塊,負責實際的數據傳輸,包括socket、文件或壓縮數據流等。
  • transport層負責以字節流方式發送和接收消息,是底層io模塊在thrift框架中的實現,每個底層io模塊都會有一個對於TTransport來負責thrift的字節流(byte stream)數據在該io模塊上的傳輸。例如,TSocket對應socket傳輸,TFileTransport對應文件傳輸。
  • TProtocol主要負責結構化數據組裝成消息,或者從消息結構中讀出結構化數據。TProtocol將一個有類型的數據轉化爲特定類型的數據。如int32會被TBinaryProtocol編碼爲一個4字節數據,或TBinaryProtocol從TTransport中取出4個字節數據解碼爲int32。
  • TServer負責接收client請求,並將請求轉發到processor進行處理。TServer主要任務是高效地接受client的請求,特別是高併發請求的狀況下快速完成請求。
  • processor負責對client的請求進行響應,包括rpc請求轉發,調用參數解析和用戶邏輯調用,返回值寫回等處理步驟。processor是服務端從thrift框架轉入用戶邏輯的關鍵流程。processor同時也負責向消息結構中寫入數據或讀出數據。

TServer

thrift核心庫提供了一個TServer抽象類。socket

TServer在thrift框架中的主要任務是接收client請求,並轉發到某個processor上進行請求處理。針對不一樣的訪問規模,thrift提供了不一樣TServer模型。thrift目前支持的server模型包括:函數

  • TSimpleServer:使用阻塞io的單線程服務器,主要用於調試。
  • TThreadedServer:使用阻塞io的多線程服務器,每個請求都在一個線程中處理,併發訪問狀況下會有不少線程同時運行。
  • TThreadPoolServer:使用阻塞io的多線程服務器,使用線程池管理處理線程。
  • TNonBlockingServer:使用非阻塞io的多線程服務器,使用少許線程既能夠完成大併發量的請求響應,必須使用TFramedTransport。

TServer對象一般以下工做:高併發

  1. 使用TServerTransport得到一個TTransport。
  2. 使用TTransportFactory,可選地將原始傳輸轉換爲一個合適的應用傳輸。
  3. 調用TProtocolFactory,爲TTransport建立一個輸入和輸出。
  4. 調用TProcessor對象的process方法。

TTransport

TTransport是與底層數據傳輸緊密相關的傳輸層。每一種支持的底層傳輸方式都存在一個與之對應的TTransport。在這一層,數據是按字節流處理的,即傳輸層看到的是一個又一個的字節,並把這些字節按順序發送和接收。TTransport並不瞭解它所傳輸的數據是什麼類型,實際上傳輸層也不關心數據是什麼類型,只須要按照字節方式對數據進行發送和接收便可。數據類型的解析在TProtocol這一層完成。編碼

TTransport具體的有如下幾個類:spa

  • TSocket:使用阻塞的TCP socket進行數據傳輸,也是最多見的模式。
  • THttpTransport:採用http傳輸協議進行數據傳輸。
  • TFileTransport:文件(日誌)傳輸類,容許client將文件傳給server,容許server將收到的數據寫到文件中。
  • TZlibTransport:與其餘transport配合使用,壓縮後對數據進行傳輸,或者將收到的數據解壓。

TProtocol

TProtocol的主要任務是把TTransport中的字節流轉換爲數據流。在TProtocol這一層就會出現具備數據類型的數據,如整型、浮點數、字符串和結構體等。TProtocol中數據雖然有了數據類型,但TProtocol只會按照指定類型將數據讀出和寫入,而對於數據的真正用途,須要在thrift自動生成的server和client中處理。

thrift可讓用戶選擇客戶端與服務端之間傳輸通訊協議的類別,在傳輸協議上整體劃分爲文本和二進制傳輸協議,以節約帶寬,提升傳輸效率,通常狀況下使用二進制類型的傳輸協議爲大多數。經常使用協議有如下幾種:

  • TBinaryProtocl:二進制編碼格式
  • TCompactProtocol:高效率的、密集的二進制編碼格式
  • TJSONProtocol:使用JSON的數據編碼協議進行數據傳輸
  • TSimpleJSONProtocol:提供JSON只寫協議,生成的文件很容易經過腳本語言解析
  • TDebugProtocol:簡單易懂的文本格式,以便於debug

TProcessor

TProcessor主要對TServer中一次請求的inputProtocol和outputProtocol進行操做,也就是從inputProtocol中讀出client的請求數據,向outputProtocol寫入用戶邏輯的返回值。TProcessorprocess是一個很是關鍵的處理函數,由於client全部的rpc調用都會通過該函數處理並轉發。

TProcessor對一次rpc調用的處理流程能夠歸納爲:

  1. TServer接收到rpc請求以後,調用TProcessorprocess進行處理。
  2. TProcessorprocess首先調用TTransport.readMessageBegin接口,讀出rpc調用的名稱和rpc調用類型。若是rpc調用類型是rpc call,則調用TProcessor.process_fn繼續處理,對於未知的rpc調用類型,則拋出異常。
  3. TProcessor.process_fn根據rpc調用名稱,到本身的processMap中查找對應的rpc處理函數。若是存在對應的rpc處理函數,則調用該處理函數繼續進行請求響應。不存在則拋出異常。

而rpc處理函數是rpc請求的最終步驟,主要有如下三個過程:

  1. 調用rpc請求參數的解析類,從TProtocol中讀入數據完成參數解析。無論rpc調用的參數有多少個,thrift都會將參數放到一個結構體中。thrift會檢查讀出參數的字段id和字段類型是否與要求的參數匹配。對於不符合要求的參數都會跳過。這樣,rpc接口發生變化以後,舊的處理函數在不作修改的狀況下,能夠經過跳過不認識的參數,來繼續提供服務。
  2. 參數解析完後,調用用戶邏輯,完成真正的請求響應。
  3. 用戶邏輯的返回值使用返回值打包類進行打包,寫入TProtocol。

ThriftClient

ThriftClient跟TProcessor同樣主要操做inputProtocol和outputProtocol,不一樣的是thriftClient將rpc調用分爲send和receive兩個步驟:

  1. send步驟,將用戶的調用參數做爲一個總體的struct寫入TProtocol,併發送到TServer。
  2. send結束後,thriftClient便當即進入receive狀態等待TServer的響應。對於TServer的響應,使用返回值解析類進行返回值解析,完成rpc調用。
相關文章
相關標籤/搜索