??? Thrift是一個跨語言的服務部署框架,最初由Facebook于2007年開發,2008年進入Apache開源項目。Thrift通過一個中間語言(IDL, 接口定義語言)來定義RPC的接口和數據類型,然后通過一個編譯器生成不同語言的代碼(目前支持C++,Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk和OCaml),并由生成的代碼負責RPC協議層和傳輸層的實現。??? Thrift實際上是實現了C/S模式,通過代碼生成工具將接口定義文件生成服務器端和客戶端代碼(可以為不同語言),從而實現服務端和客戶端跨語言的支持。用戶在Thirft描述文件中聲明自己的服務,這些服務經過編譯后會生成相應語言的代碼文件,然后用戶實現服務(客戶端調用服務,服務器端提服務)便可以了。其中protocol(協議層, 定義數據傳輸格式,可以為二進制或者XML等)和transport(傳輸層,定義數據傳輸方式,可以為TCP/IP傳輸,內存共享或者文件共享等)被用作運行時庫。?基本概念
Thrift中的幾個概念:
Server 服務模型
Handler 數據處理接口
Processor 數據處理對象
Protocol 數據傳輸協議
Transport 數據傳輸方式Handler為抽象接口,需要在編譯后的代碼上自行實現。Processor調用Handler中的代碼,編譯自動生成,不用關心。?(1)支持的傳輸格式
TBinaryProtocol – 二進制格式.
TCompactProtocol – 壓縮格式
TJSONProtocol – JSON格式
TSimpleJSONProtocol –提供JSON只寫協議, 生成的文件很容易通過腳本語言解析。
TDebugProtocol – 使用易懂的可讀的文本格式,以便于debug
(2) 支持的數據傳輸方式
TFileTransport:文件(日志)傳輸類,允許client將文件傳給server,允許server將收到的數據寫到文件中。
THttpTransport:采用Http傳輸協議進行數據傳輸
TSocket:采用TCP Socket進行數據傳輸
TZlibTransport:壓縮后對數據進行傳輸,或者將收到的數據解壓
下面幾個類主要是對上面幾個類地裝飾(采用了裝飾模式),以提高傳輸效率。
TBufferedTransport:對某個Transport對象操作的數據進行buffer,即從buffer中讀取數據進行傳輸,或者將數據直接寫入buffer
TFramedTransport:以frame為單位進行傳輸,非阻塞式服務中使用。同TBufferedTransport類似,也會對相關數據進行buffer,同時,它支持定長數據發送和接收。
TMemoryBuffer:從一個緩沖區中讀寫數據?(3)支持的服務模型
TSimpleServer – 簡單的單線程服務模型,常用于測試
TThreadedServer - 多線程服務模型,使用阻塞式IO,每個請求創建一個線程。
TThreadPoolServer – 線程池服務模型,使用標準的阻塞式IO,預先創建一組線程處理請求。
TNonblockingServer – 多線程服務模型,使用非阻塞式IO(需使用TFramedTransport數據傳輸方式)?處理大量更新的話,主要是在TThreadedServer和TNonblockingServer中進行選擇。TNonblockingServer能夠使用少量線程處理大量并發連接,但是延遲較高;TThreadedServer的延遲較低。實際中,TThreadedServer的吞吐量可能會比TNonblockingServer高,但是TThreadedServer的CPU占用要比TNonblockingServer高很多。?安裝與使用thrift的安裝需要注意實現安裝一些庫。
thrift的C++編譯器使用了boost中的shared_ptr,如果需要配合c++使用的話,需要先安裝boost。
如果要使用NonBlockingServer的話,需要安裝libevent。?thrift的使用的時候,首先定義一個idl文件(interface description language),然后使用thrift編譯出相應的代碼。thrift --gen cpp XYZ.thrift我們需要記住的是: Thrift幫你生成了給定Service的服務器端和客戶端代碼.Thrift這里的命名規則是對于Service XYZ, 它對應的服務器端代碼(具體這個Service的執行)在類XYZHandler中,客戶端代碼(負責marshall, execute RPC)在類XYZClient中. 所以你需要用這個服務, 你只需要直接修改或者繼承這些類.?服務器編寫的一般步驟:
1. 創建Handler
2. 基于Handler創建Processor
3. 創建Transport
4. 創建Protocol方式
5. 基于Processor, Transport和Protocol創建Server
6. 運行Server?客戶端編寫的一般步驟:
1. 創建Transport
2. 創建Protocol方式
3. 基于Transport和Protocol創建Client
4. 運行Client的方法?創建Transport的時候,一般都需要創建相應的Socket。?示例代碼附上一份周末寫的測試代碼,用thrift將leveldb封裝了一個網絡服務。其中包含各種服務模型。?kv.rar? ????需要注意的問題1. Thrift生成的server端是thread safe的. 但是client端不是thread safe. 所以需要多個thread和server端通信,則每個thread需要initiate一個自己的client實例.2. 如果服務器采用TNonblockingServer的話,客戶端必須采用TFramedTransport。程序鏈接的時候需要thriftnb。
3. 默認TServerSocket和TSocket都設置了NoDelay為1,使得報文盡快發送出去,如果客戶端和服務器間傳輸數據量較大,通過可以設置NoDelay為0來開啟Nagel算法,緩存一段數據后再進行發送,減少報文數量。
TSocket默認開啟了Linger,并設置linger time為0,這樣close會丟棄socket發送緩沖區中的數據,并向對端發送一個RST報文,close不會被阻塞,立即返回。
TServerSocket默認關閉了Linger,close不會被阻塞,立即返回。
4. fb303作為handler的基類,里面預置了一些rpc方法,用于監控,包括系統狀態,請求次數等狀態信息。
thrift文件中需要include "fb303.thrift"這樣來將service導入目標thrift文件中。thrift編譯后的代碼只需要相應的Handler多重繼承facebook::fb303::FacebookBase就好了。
- class scribeHandler : virtual public scribe : : thrift : : scribeIf ,
- ?????????????????????????????? public facebook : : fb303 : : FacebookBase {
5. 可以將ZeroMQ等作為transport使用其zeromq來進行通訊。
?可以參考thrift-0.7.0/contrib/zeromq中的代碼。【未進行測試】
https://issues.apache.org/jira/browse/THRIFT-812
6. thrift支持完全async,生成代碼的時候需要使用
?thrift --gen cpp:cob_style xxx.thrift
這樣的話,生成的代碼需要TEventServer.h,但是async目錄下沒有,只有TEvhttpServer.h
https://github.com/klickverbot/thrift/commit/5ddabb8e3f63a15874e436c9a650dc17f7dd7028#diff-2?【注意】async有些問題,編譯自動生成的代碼需要TEventServer.h(0.7.0和svn trunk都是如此),但是thrift中沒有這個文件。contrib/async中有一個http的異步測試代碼,大致看了一下實現,使用std::tr1::function和std::tr1::bind實現完成回調函數,實現Processor的異步處理,增加了TAsyncProcessor,其process函數返回的時候,真正的邏輯可能沒有完成,依賴完成回調函數處理請求完成的部分,對于服務器端來講主要是將response發送給客戶端。一般RPC業務同步的TProcessor就可以了,只有類似proxy這種中間服務需要異步處理,不過當前thrift中只有TEvhttpServer可用;-)? ?
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
