Thrift與其說他傳輸方式的比較

Thrift與其他傳輸方式的比較

Thrift  是什麼?
  Thrift源於大名鼎鼎的facebook之手,在2007年facebook提交Apache基金會將Thrift作爲一個開源項目,對於當時的facebook來說創造thrift是爲了解決facebook系統中各系統間大數據量的傳 輸通信以及系統之間語言環境不同需要跨平臺的特性。所以thrift可以支持多種程序語言,例如:  C++, C#, Cocoa, Erlang, Haskell, Java, Ocami, Perl, PHP, Python, Ruby, Smalltalk. 在多種不同的語言之間通信thrift可以作爲二進制的高性能的通訊中間件,支持數據(對象)序列化和多種類型的RPC服務。Thrift適用於程序對程 序靜態的數據交換,需要先確定好他的數據結構,他是完全靜態化的,當數據結構發生變化時,必須重新編輯IDL文件,代碼生成,再編譯載入的流程,跟其他IDL工具相比較可以視爲是Thrift的弱項,Thrift適用於搭建大型數據交換及存儲的通用工具,對於大型系統中的內部數據傳輸相對於JSON和xml無論在性能、傳輸大小上有明顯的優勢。

   Thrift是IDL(interface definition language)描述性語言的一個具體實現,關於IDL的話題我們可以追溯到CORBA盛行1999-2001年(Common Object Request Broker Architecture/公用對象請求代理體系結構),在 IDL 中我們似乎不會忘記到這幾個關鍵字:module、interface、string、long 和 int,我還記得IDL利用module來創建名稱空間,並且準確地映射爲 Java 的 package,這些特性幾乎和現在thrift的特性完全相同,所以thrift的設計思想和理念絕不是什麼從火星來的new idea,看看在那個CORBA盛行的年代人們提出的概念,如圖所示CORBA 請求的各個部分,回頭我們再與thrift進行對比一下:

Common Object Request Broker Architecture

Thrift 基礎架構
   Thrift是一個服務端和客戶端的架構體系,從我個人的感官上來看Thrift是一個類似XML-RPC+Java-to- IDL+Serialization Tools=Thrift 的東東,Thrift 具有自己內部定義的傳輸協議規範(TProtocol)和傳輸數據標準(TTransports),通過IDL腳本對傳輸數據的數據結構(struct) 和傳輸數據的業務邏輯(service)根據不同的運行環境快速的構建相應的代碼,並且通過自己內部的序列化機制對傳輸的數據進行簡化和壓縮提高高併發、 大型系統中數據交互的成本,下圖描繪了Thrift的整體架構,分爲6個部分:1.你的業務邏輯實現(You Code) 2.客戶端和服務端對應的Service 3.執行讀寫操作的計算結果4.TProtocol 5.TTransports  6.底層I/O通信
thrift

圖 中前面3個部分是1.你通過Thrift腳本文件生成的代碼,2.圖中的褐色框部分是你根據生成代碼構建的客戶端和處理器的代碼,3.圖中紅色的部分是2 端產生的計算結果。從TProtocol下面3個部分是Thrift的傳輸體系和傳輸協議以及底層I/O通信,Thrift並且提供 堵塞、非阻塞,單線程、多線程的模式運行在服務器上,還可以配合服務器/容器一起運行,可以和現有JEE服務器/Web容器無縫的結合。

數據類型
     * Base Types:基本類型
     * Struct:結構體類型
     * Container:容器類型,即List、Set、Map
     * Exception:異常類型
     * Service: 定義對象的接口,和一系列方法

協議
  Thrift可以讓你選擇客戶端與服務端之間傳輸通信協議的類別,在傳輸協議上總體上劃分爲文本(text)和二進制(binary)傳輸協議, 爲節約帶寬,提供傳輸效率,一般情況下使用二進制類型的傳輸協議爲多數,但有時會還是會使用基於文本類型的協議,這需要根據項目/產品中的實際需求:
    * TBinaryProtocol – 二進制編碼格式進行數據傳輸。
    * TCompactProtocol – 這種協議非常有效的,使用Variable-Length Quantity (VLQ) 編碼對數據進行壓縮。
    * TJSONProtocol – 使用JSON的數據編碼協議進行數據傳輸。
    * TSimpleJSONProtocol – 這種節約只提供JSON只寫的協議,適用於通過腳本語言解析
    * TDebugProtocol – 在開發的過程中幫助開發人員調試用的,以文本的形式展現方便閱讀。

傳輸層
    * TSocket- 使用堵塞式I/O進行傳輸,也是最常見的模式。
    * TFramedTransport- 使用非阻塞方式,按塊的大小,進行傳輸,類似於Java中的NIO。
    * TFileTransport- 顧名思義按照文件的方式進程傳輸,雖然這種方式不提供Java的實現,但是實現起來非常簡單。
    * TMemoryTransport- 使用內存I/O,就好比Java中的ByteArrayOutputStream實現。
    * TZlibTransport- 使用執行zlib壓縮,不提供Java的實現。

服務端類型
    * TSimpleServer -  單線程服務器端使用標準的堵塞式I/O。
    * TThreadPoolServer -  多線程服務器端使用標準的堵塞式I/O。
    * TNonblockingServer – 多線程服務器端使用非堵塞式I/O,並且實現了Java中的NIO通道。
 
誰在用thrift ?

Quara
     Thrift用於Quara系統後端數據的通信,服務端是用C++來實現的,客戶端則是python。
Quara背景:Quara是在線問答服務公司,類似新浪微博和百度知道的合體,消息靈通人士透露,去年Quara獲得了1400萬美元投資,目前他們只有9名員工。
原文:http://www.philwhln.com/quoras-technology-examined#thrift

Evernote
  Thrift用於在多種Evernote API平臺開發的客戶端與Evernote服務器之間的通信與數據傳輸,Evernote API定義了自己的Evernote Data Access and Management (EDAM) 協議規範,讓客戶端使用更小的網絡帶寬上傳、下載文件和在線即時搜索服務。
Evernote 背景:EverNote是一款非常著名的免費軟件,它最大的特點就是支持多平臺,而且數據能通過網絡互相同步。譬如說,你可以隨時在手機上的Evernote新增筆記,回家後在電腦上也能看到它了!
原文:http://www.evernote.com/about/developer/api/evernote-api.htm

HBase 中的Thrift
    Thrift用於HBase中是爲了提供跨平臺的服務接口,在HBase 中可以使用[hbase-root]/bin/hbase thrift start 命令啓動涵蓋Thrift的HBase服務端,客戶端通過thrift的命令生成不同版本的客戶端代碼,根據定義的數據格式,對遠程HBase服務端進行 操作,是除了REST遠程方法調用的另一種途徑。
參見:http://wiki.apache.org/hadoop/Hbase/ThriftApi

更多資料請閱讀:http://wiki.apache.org/thrift/PoweredBy

Thrift與其他傳輸方式的比較
    xml與JSON相比體積太大,但是xml傳統,也不算複雜。
    json 體積較小,新穎,但不夠完善。
    thrift 體積超小,使用起來比較麻煩,不如前兩者輕便,但是對於1.高併發、2.數據傳輸量大、3.多語言環境, 滿足其中2點使用 thrift還是值得的。

  假定需要傳輸相同的內容,但使用不同的方式從 1、傳輸內容所產生的大小 2、傳輸過程中服務端和客戶端所產生的開銷,這2個方便進行比較。使用Thrift和其他方式的所產生的內容大小比較結果如下:
     thrift-size
    在上圖中我們能明顯看出,最臃腫的是RMI,其次是xml,使用Thrift的TCompactProtocol協議和Google 的 Protocol Buffers 相差的不算太多,相比而言還是Google 的 Protocol Buffers效果最佳。

使用Thrift 中的協議和其他方式的所產生的運行開銷比較結果如下:
  thrift-load

   在上圖中我們能明顯看出,最佔資源是REST2中協議,使用Thrift的TCompactProtocol協議和Google 的 Protocol Buffers 相差的不算太多,相比而言Thrift的TCompactProtocol協議效果最佳。

 

 

一、開發環境(清單1)
1.操作系統
    Server-Linux / Client-WinXP
2.SDK
    Sun JDK1.5+

3.需要的jar依賴包
    libthrift.jar
    slf4j-api-1.5.8.jar
    slf4j-log4j12-1.5.8.jar
    log4j-1.2.15.jar

4.編譯工具
    Apache Ant  & Apache ivy

二、安裝/配置 (清單2)
    1.下載thrift源文件
        http://labs.renren.com/apache-mirror//incubator/thrift/0.5.0-incubating/thrift-0.5.0.tar.gz
        
    2.編譯thrift源文件
        1)解壓 thrift-0.5.0.tar.gz 
        2)用ant編譯源代碼,進入x:/thrift-0.5.0/lib/java目錄,執行ant,通過ant中的ivy工具會自動從站點下載所需要的依賴包,編譯完成後如圖所示:
         /img/2013/04/11/115822984.png
        3)編譯過程中下載的依賴包在x:/thrift-0.5.0/lib/java/build/ivy/lib 目錄下可以看見下載的jar依賴包,將編譯成功以後的jar包加入Eclipse的開發環境中。

三、腳本文件(清單3)
    1.創建腳本
        創建腳本文件 testJava.thrift ,腳本文件內容如下:
        namespace java com.javabloger.gen.code   # 註釋1   定義生成代碼的命名空間,與你需要定義的package相對應。

        struct Blog {   #  註釋2.1   定義實體名稱和數據結構,類似你業務邏輯中的pojo get/set
            1: string topic     #  註釋2.2  參數類型可以參見 Thrift wiki   
            2: binary content  
            3: i64    createdTime
            4: string id
            5: string ipAddress
            6: map<string,string> props
          }
        service ThriftCase {  #  註釋3    代碼生成的類名,你的業務邏輯代碼需要實現代碼生成的ThriftCase.Iface接口
            i32 testCase1(1:i32 num1, 2:i32 num2, 3:string  num3) #註釋4.1 方法名稱和方法中的入參,入參類型參見wiki
            list<string> testCase2(1:map<string,string>  num1)
            void testCase3()
            void testCase4(1:list<Blog> blog)   #  註釋4.2   list 是thrift中基本數據類型中的一種,list中包含的Blog對象是上面struct中定義的
        }

    2.運行腳本
        1)從 thrift 站點下載windows版本的編譯工具,下載地址:http://labs.renren.com/apache-mirror//incubator/thrift/0.5.0-incubating/thrift-0.5.0.exe
        2)通過Thrift的腳本文件,運行 thrift 命令創建生成的代碼,例如:執行 thrift -gen java x:/testJava.thrift  命令,在當前運行的盤符下,可看見gen-java目錄,在這裏目錄中可以看見生成的java代碼,更多thrift 命令內容,請參見thrift命令自帶的help。

3.Thrift 中的基本數據類型 (清單4)
    類型 描述
    bool true, false
    byte 8位的有符號整數
    i16 16位的有符號整數
    i32 32位的有符號整數
    i64 64位的有符號整數
    double 64位的浮點數
    string UTF-8編碼的字符串
    binary 字符數組
    struct 結構體
    list 有序的元素列表,類似於STL的vector
    set 無序的不重複元素集,類似於STL的set
    map key-value型的映射,類似於STL的map
    exception 是一個繼承於本地語言的exception基類
    service 服務。包含多個函數接口(純虛函數)

 

四、創建代碼(清單5)
    我將示例工程分了4個包,如下所示:
     /com/javabloger
            /client               # 1.客戶端測試代碼
            /gen/code              # 2.通過腳本生成的class
            /layer/transport       # 3.服務器端代碼和定義的傳輸協議
            /layer/business      # 4.具體的業務邏輯代碼
    具體代碼內容這裏就不闡述了,重點是要明白代碼的結構和層次關係,其次是裏面主要的幾個類的含義,至於代碼是怎麼寫的並不是非常重要,僅僅是我個人觀點,僅供參考,謝謝。

代碼示例的下載地址: http://javabloger-mini-books.googlecode.com/files/Thritf.zip

五、運行程序
    先運行server,再運行client ,客戶端向服務器端發送數據調用服務器端的4個方法,服務器端被傳入客戶端數據,運行效果如圖所示:
    run-thirtf-code.png

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章