Thrift最初是由Facebook開發的,因為隨著流量和網路結構的擴充套件,一些操作如搜尋、分發、事件日誌記錄等已經超出系統的處理範圍,所以Facebook的工程師開發服務時選擇了多種不同的程式語言來達到滿意的效能、快速開發、已有庫的重用。Thrift於2007年4月開源並於2008年5月進入Apache孵化器,在2010年10月成為Apache TLP。

Thrift是一個可擴充套件的跨語言服務的軟體開發框架,目標是儘可能高效和無縫地跨語言進行可靠的高效能通訊和資料序列化,Thrift通過中間語言(IDL, 介面定義語言)來定義RPC的介面和資料型別,利用程式碼生成器生成不同語言的程式碼(如C++,Java, Python, PHP. . .等),並由生成的程式碼負責RPC協議層和傳輸層的實現。

Thrift網路堆疊

   +-------------------------------------------+

  1. | Server |
  2. | (single-threaded, event-driven etc) |
  3. +-------------------------------------------+
  4. | Processor |
  5. | (compiler generated) |
  6. +-------------------------------------------+
  7. | Protocol |
  8. | (JSON, compact etc) |
  9. +-------------------------------------------+
  10. | Transport |
  11. | (raw TCP, HTTP etc) |
  12. +-------------------------------------------+

傳輸(Transport)

傳輸層為網路讀取/寫入網路提供了一個簡單的抽象,這使得Thrift能夠將底層傳輸與系統其它部分分離(如序列化/反序列化)。下面是一些Transport介面支援的方法

● open

● close

● read

● write

● flush

另外Thrift還提供了用於接收和建立基本Transport物件的ServerTransport介面。顧名思義,ServerTransport主要用於伺服器端,為傳入連線建立新的Transport物件。ServerTransport介面支援的方法

  1. open
  2. listen
  3. accept
  4. close

協議(Protocol)

協議層抽象定義了將記憶體資料結構對映為傳輸格式的機制。換句話說,一個協議規定了資料型別如何使用Transport來對自身進行編碼/解碼。因此,協議實現管理編碼方案並負責序列化和反序列化。Protocol實現的一些例子包括JSON,XML,純文字,緊湊二進位制等。

Protocol介面有

  1. writeMessageBegin(name, type, seq)
  2. writeMessageEnd()
  3. writeStructBegin(name)
  4. writeStructEnd()
  5. writeFieldBegin(name, type, id)
  6. writeFieldEnd()
  7. writeFieldStop()
  8. writeMapBegin(ktype, vtype, size)
  9. writeMapEnd()
  10. writeListBegin(etype, size)
  11. writeListEnd()
  12. writeSetBegin(etype, size)
  13. writeSetEnd()
  14. writeBool(bool)
  15. writeByte(byte)
  16. writeI16(i16)
  17. writeI32(i32)
  18. writeI64(i64)
  19. writeDouble(double)
  20. writeString(string)
  21.  
  22. name, type, seq = readMessageBegin()
  23. readMessageEnd()
  24. name = readStructBegin()
  25. readStructEnd()
  26. name, type, id = readFieldBegin()
  27. readFieldEnd()
  28. k, v, size = readMapBegin()
  29. readMapEnd()
  30. etype, size = readListBegin()
  31. readListEnd()
  32. etype, size = readSetBegin()
  33. readSetEnd()
  34. bool = readBool()
  35. byte = readByte()
  36. i16 = readI16()
  37. i32 = readI32()
  38. i64 = readI64()
  39. double = readDouble()
  40. string = readString()

Thrift的Protocol是面向流設計的,因此沒有必要去顯式分幀(framing)。比如,在開始序列化之前我們可以不用關心我們傳輸的字串長度或者列表中元素的個數。在Thrift支援的大部分程式語言中可供使用的Protocol型別有:

  • binary:簡單二進位制編碼–欄位長度和型別被編碼成二進位制並緊跟在實際欄位值後面
  • compat: 詳情見THRIFT-110
  • json

處理層(Processor)

處理層封裝了從輸入流中讀取資料並寫入輸出流的能力。Protocol物件即代表輸入流和輸出流。Processor介面非常簡單。

  1. interface TProcessor {
  2. bool process(TProtocol in, TProtocol out) throws TException
  3. }

特定服務的Processor由編譯器自動生成實現。Processor通過輸入Protocol從網路上讀取資料,並將資料處理代理給使用者實現的Handler,最後通過輸出Protocol將資料寫回到網路上。

伺服器層(server)

伺服器層將上述所有各種功能彙集在一起​​:

  • 建立一個Transport
  • 為Transport建立輸入/輸出Protocol
  • 基於輸入/輸出Protocol建立一個Processor
  • 等待傳入連線並將它們交給處Processor