Thrift RPC實戰(三) Thrift序列化機制

1.Thrift基礎架構    

Thrift是一個客戶端和服務端的架構體系,數據經過socket傳輸;java

具備本身內部定義的傳輸協議規範(TProtocol)和傳輸數據標準(TTransports);apache

經過IDL腳本對傳輸數據的數據結構(struct) 和傳輸數據的業務邏輯(service)根據不一樣的運行環境快速的構建相應的代碼;數據結構

經過本身內部的序列化機制對傳輸的數據進行簡化和壓縮提升高併發、 大型系統中數據交互的性能。架構

  (1)  Thrift 數據類型

基本類型:
  bool: 布爾值
  byte: 8位有符號整數
  i16: 16位有符號整數
  i32: 32位有符號整數
  i64: 64位有符號整數
  double: 64位浮點數
  string: UTF-8編碼的字符串
  binary: 二進制串
結構體類型:
  struct: 定義的結構體對象
容器類型:
  list: 有序元素列表
  set: 無序無重複元素集合
  map: 有序的key/value集合
異常類型:
  exception: 異常類型
服務類型:
  service: 具體對應服務的類併發

  (2)  協議

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

(3)傳輸層

    一、TSocket- 使用堵塞式I/O進行傳輸,也是最多見的模式。
    二、TFramedTransport- 使用非阻塞方式,按塊的大小,進行傳輸,相似於Java中的NIO。
    三、TFileTransport- 顧名思義按照文件的方式進程傳輸,雖然這種方式不提供Java的實現,可是實現起來很是簡單。
    四、TMemoryTransport- 使用內存I/O,就比如Java中的ByteArrayOutputStream實現。高併發

    五、TZlibTransport- 使用執行zlib壓縮,不提供Java的實現。性能

(3)服務服務模型

        http://www.javashuo.com/article/p-cmuzhusi-cg.htmlui

2.Thrift序列化機制

Thrift提供了可擴展序列化機制, 不但兼容性好並且壓縮率高。編碼

   thrift 數據格式描述

   thrift的向後兼容性(Version)藉助屬性標識(數字編號id + 屬性類型type)來實現, 能夠理解爲在序列化後(屬性數據存儲由 field_name:field_value => id+type:field_value)

 咱們定義IDL文件形如

namespace java stu.thrift;
 
struct User {
  1: required string name
  2: required string address
}

thrift的向後兼容性(Version)藉助屬性標識(數字編號id + 屬性類型type)來實現, 能夠理解爲在序列化後(屬性數據存儲由 field_name:field_value => id+type:field_value), 這也解釋了上述提到的場景的緣由了.
 進行代碼解讀:

public void read(org.apache.thrift.protocol.TProtocol iprot, User struct) throws org.apache.thrift.TException {
  org.apache.thrift.protocol.TField schemeField;
     //讀取結構開始標記
  iprot.readStructBegin();
  while (true)
  {
    // 讀取Field屬性開始標記
    schemeField = iprot.readFieldBegin();
    if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
      break;
    }
    switch (schemeField.id) {
      case 1: // name
        if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
          struct.name= iprot.readString();
          struct.setNameIsSet(true);
        } else { 
          org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
        }
        break;
      case 2: // address
        if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
          struct.address= iprot.readString();
          struct.setAddressIsSet(true);
        } else { 
          org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
        }
        break;
      default:
        org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
    }
    iprot.readFieldEnd();
  }
  iprot.readStructEnd();

  // check for required fields of primitive type, which can't be checked in the validate method
  struct.validate();
}

最終會被細化爲readStructBegin, readFieldBegin, read<type>(readString, readI32, readI64), readFieldEnd, readStructEnd的有組織有序調用.

Thrift官方文檔, 也提到對新增的字段屬性, 採用id遞增的方式標識並以optional修飾來添加.

相關文章
相關標籤/搜索