昨天總結了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(); } }
新手入門,根據自己的理解以及拜閱了網友們的文章總結的難免有不當之處的,輕噴.