Thrift入門初探(2)--thrift基礎知識詳解


  昨天總結了thrift的安裝和入門實例,Thrift入門初探--thrift安裝及java入門實例,今天開始總結一下thrift的相關基礎知識.

  Thrift使用一種中間語言IDL,來進行接口的定義,下面來具體講一下IDL可定義的幾種常用數據類型和關鍵字.

常用數據類型及關鍵字

  基本類型

    thrift不支持無符號的類型,無符號類型可以簡單理解為不能表示負數,只能表示正數的類型,像java的基本數據類型都是有符號的類型.

  • byte:有符號字節
  • i32:32位有符號整數,此外還有i16,i64
  • double:64位浮點數
  • string:二進制字符串
  • bool 布爾值 true或false

  結構體類型(struct):

    類似於c語言的結構體定義,在java中會被轉化為javabean類

struct User {
  1: i32 id;
  2: string name;
  3: double salary;
  4: bool hasCar;
}

  服務類型(service):

    service:對應服務的接口,內部可定義各種方法,相當於java中創建interface一樣,創建的service經過代碼生成命令會生成客戶端,服務端的框架代碼

service Hello{
  string helloString(1:string s);
  i32 helloInt(1:i32 i);
  bool helloBoolean(1:bool b);
  void helloVoid();
  string helloNull();
}

  異常類型(Exception):

exception RequestException {

  1:i32 code;

  2:string detail;

}

  容器類型

    集合中的元素可以是除了service之外的任意類型

   list<T>:有序列表,元素可重復

   set<T>:無需集合,元素不可重復

   map<K,V>:鍵值對集合

  枚舉類型

  enum Color{

    RED,

    BLUE

  }

  命名空間(namespace)

    可以理解成java中的packet,用於避免一些代碼沖突,每種語言都有屬於自己的命名空間的方式,比如java語言,就可以使用java語言的格式

namespace java com.wang.project

   此外還有一些語言特性和關鍵字就不一一介紹了,比如可選參數和必選參數,required和optional,定義常量const,引入文件include等

Thrift支持的傳輸協議

  Thrift支持多種傳輸協議,我們可以根據自己的需要來選擇合適的類型,總體上來說,分為文本傳輸和二進制傳輸,由於二進制傳輸在傳輸速率和節省帶寬上有優勢,所以大部分情況下使用二進制傳輸是比較好的選擇.

  • TBinaryProtocol:使用二進制編碼格式傳輸,是thrift的默認傳輸協議
  • TCompactProtocol:使用壓縮格式傳輸
  • TJSONProtocol :使用JSON格式傳輸
  • TDebugProtocol – 使用易懂可讀的文本格式進行傳輸,以便於debug
  • TSimpleJSONProtocol – 提供JSON只寫的協議,適用於通過腳本語言解析

Thrift支持的傳輸模式

  Thrift封裝了一層傳輸層來支持底層的網絡通信,在Thrift中稱為Transport,不僅提供open,close,flush等方法,還有一些read/write方法.

  •   TSocket:阻塞式IO的Transport實現,用在客戶端.
  •   TServerSocket:非阻塞式Socket,用於服務器端,用於監聽TSocket.
  •   TNonblockingSocket:非阻塞式IO的實現
  •   TMemoryInputTransport: 封裝了一個字節數組byte[]來做輸入流的封裝
  •   TFramedTransport- 同樣使用非阻塞方式,按塊的大小進行傳輸,輸入流封裝了TMemoryInputTransport  

Thrift支持的服務模型

  TSimpleServer:

    這種工作模式只有一個線程,循環監聽傳過來的請求並對其進行處理,處理完才能接受下一個請求,是一種阻塞式IO的實現,因為效率比較低,實際線上環境一般用不到.一般用於開發時候演示工作流程時使用.  

  TNonblockingServer:

    這種模式與TsimpleServer最大的區別就是使用NIO,也就是非阻塞是IO的方式實現IO的多路復用,它可以同時監聽多個socket的變化,但因為業務處理上還是單線程模式,所以在一些業務處理比較復雜耗時的時候效率還是不高,因為多個請求任務依然需要排隊一個一個進行處理.

  TThreadPoolServer:

    這種模式引入了線程池,主線程只負責accept,即監聽Socket,當有新的請求(客戶端Socket)來時,就會在線程池里起一個線程來處理業務邏輯,這樣在並發量比較大的時候(但不超過線程池的數量)每個請求都能及時被處理,效率比較高,但一旦並發量很大的時候(超過線程池數量),后面來的請求也只能排隊等待.

  TThreadedSelectorServer:

    這是一種多線程半同步半異步的服務模型,是Thrift提供的最復雜最高級的服務模型,內部有一個專門負責處理監聽Socket的線程,有多個專門處理業務中網絡IO的線程,有一個專門負責決定將新Socket連接分配給哪一個線程處理的起負載均衡作用的線程,還有一個工作線程池.這種模型既可以響應大量並發連接的請求又可以快速對wangluoIO進行讀寫,能適配很多場景,因此是一種使用比較高頻的服務模型.

Thrift服務層編碼

try {
            System.out.println("服務端開啟....");
            //1.創建TProcessor
            TProcessor tprocessor = new Hello.Processor<Hello.Iface>(new HelloServiceImpl());
            // 2.創建TserverTransport
            TServerSocket serverTransport = new TServerSocket(9898);
            //3.創建TProtocol
            TBinaryProtocol.Factory factory = new TBinaryProtocol.Factory();

            TServer.Args tArgs = new TServer.Args(serverTransport);
            tArgs.processor(tprocessor);
            tArgs.protocolFactory(factory);
            //4.創建Tserver,傳入需要的參數,server將以上內容集成在一起
            TServer server = new TSimpleServer(tArgs);
            //5.啟動server
            server.serve();
            }catch (TTransportException e) {
            e.printStackTrace();
        }

根據代碼可以看出服務端編碼基本流程:

  0.實現服務處理接口impl,重寫接口方法.

  1.創建TProcessor

  Processor封裝了從輸入數據流中讀數據和向數據流中寫數據的操作,與服務相關的Processor是由編譯器編譯IDL文件產生的,它的主要工作是:從連接中讀取數據,把處理交給用戶實現impl,最后把結果寫到連接上.

  2.創建serverTransport

  TServerSocket是ServerTransport的阻塞式IO的實現.它實現了監聽端口的作用,accept到的Socket類型都是客戶端的TSocket類型(阻塞式Socket).

  3.創建TProtocol

  TProtocol定義了基本的協議信息,包括傳輸什么數據,如何解析傳輸的數據.   

  4.創建server

  根據需要選擇使用不同的服務模式,代碼中為了演示只是用了最簡單TSimpleServer

  5.啟動服務

Thrift客戶端編碼

System.out.println("客戶端啟動....");
        TTransport transport = null;
        try {
            //1.創建TTransport
            transport = new TSocket("localhost", 9898, 30000);
            // 2.創建TProtocol  協議要和服務端一致
            TProtocol protocol = new TBinaryProtocol(transport);
            //3.創建Client 打開transport
            Hello.Client client = new Hello.Client(protocol);
            transport.open();
            //4.調用Client響應方法
            String result = client.helloString("哈哈");
            System.out.println("Thrify client result =: " + result);
        } catch (TTransportException e) {
            e.printStackTrace();
        } catch (TException e) {
            e.printStackTrace();
        } finally {
            if (null != transport) {
                transport.close();
            }
        }

   新手入門,根據自己的理解以及拜閱了網友們的文章總結的難免有不當之處的,輕噴.

相關博文

Thrift入門初探--thrift安裝及java入門實例

  參考資料

Thrift源碼分析(六)-- Transport傳輸層分析

和 Thrift 的一場美麗邂逅

thrift入門教程


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM