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修饰来添加.

相关文章
相关标签/搜索