Apache Thrift 官网学习 四 基础知识掌握

四 序列化机制

4.1 基本知识

  • Thrift支持二进制压缩格式,以及json格式数据的序列化反序列化。开发人员可以更加灵活的选择协议的具体形式。协议是可自由扩展的,新版本的协议,完全兼容老的版本!
  • 前面介绍到了protocol的一些基本知识,下面我们来详细看下他的用法

4.2 TProtocol

  • 这是一个协议接口,我们可以看出他有多少个实现类

image.png

  • TBinaryProtocol:是Thrift的默认协议,使用二进制编码格式进行数据传输,基本上直接发送原始数据
  • TCompactProtocol:压缩的、密集的数据传输协议,基于Variable-length quantity的zigzag 编码格式
  • TJSONProtocol:以JSON (JavaScript Object Notation)数据编码协议进行数据传输
  • TDebugProtocol:常常用以编码人员测试,以文本的形式展现方便阅读

基本方法

  /**
   * Writing methods. 写方法
   */

  public abstract void writeMessageBegin(TMessage message) throws TException;

  public abstract void writeMessageEnd() throws TException;

  public abstract void writeStructBegin(TStruct struct) throws TException;

  public abstract void writeStructEnd() throws TException;

  public abstract void writeFieldBegin(TField field) throws TException;

  public abstract void writeFieldEnd() throws TException;

  public abstract void writeFieldStop() throws TException;

  public abstract void writeMapBegin(TMap map) throws TException;

  public abstract void writeMapEnd() throws TException;

  public abstract void writeListBegin(TList list) throws TException;

  public abstract void writeListEnd() throws TException;

  public abstract void writeSetBegin(TSet set) throws TException;

  public abstract void writeSetEnd() throws TException;

  public abstract void writeBool(boolean b) throws TException;

  public abstract void writeByte(byte b) throws TException;

  public abstract void writeI16(short i16) throws TException;

  public abstract void writeI32(int i32) throws TException;

  public abstract void writeI64(long i64) throws TException;

  public abstract void writeDouble(double dub) throws TException;

  public abstract void writeString(String str) throws TException;

  public abstract void writeBinary(ByteBuffer buf) throws TException;

  /**
   * Reading methods. 读方法
   */

  public abstract TMessage readMessageBegin() throws TException;

  public abstract void readMessageEnd() throws TException;

  public abstract TStruct readStructBegin() throws TException;

  public abstract void readStructEnd() throws TException;

  public abstract TField readFieldBegin() throws TException;

  public abstract void readFieldEnd() throws TException;

  public abstract TMap readMapBegin() throws TException;

  public abstract void readMapEnd() throws TException;

  public abstract TList readListBegin() throws TException;

  public abstract void readListEnd() throws TException;

  public abstract TSet readSetBegin() throws TException;

  public abstract void readSetEnd() throws TException;

  public abstract boolean readBool() throws TException;

  public abstract byte readByte() throws TException;

  public abstract short readI16() throws TException;

  public abstract int readI32() throws TException;

  public abstract long readI64() throws TException;

  public abstract double readDouble() throws TException;

  public abstract String readString() throws TException;

  public abstract ByteBuffer readBinary() throws TException;

4.3 TCompactProtocol

  • TCompactProtocol2 是 THRIFT-110 中指定的紧凑协议的 Java 实现。减少结构开销的基本方法是 a) 在所有地方使用可变长度整数 b) 尽可能使用未使用的位。
  • 您的节省显然会根据结构的具体构成而有所不同,但总的来说,您拥有的字段、嵌套结构、短字符串和集合以及低值 i32 和 i64 字段越多,您将看到的好处就越多。
  • 所有类型:
/**
   * All of the on-wire type codes.
   */
  private static class Types {
    public static final byte BOOLEAN_TRUE   = 0x01;
    public static final byte BOOLEAN_FALSE  = 0x02;
    public static final byte BYTE           = 0x03;
    public static final byte I16            = 0x04;
    public static final byte I32            = 0x05;
    public static final byte I64            = 0x06;
    public static final byte DOUBLE         = 0x07;
    public static final byte BINARY         = 0x08;
    public static final byte LIST           = 0x09;
    public static final byte SET            = 0x0A;
    public static final byte MAP            = 0x0B;
    public static final byte STRUCT         = 0x0C;
  }

源码分析

package com.example.thrift.client;

import com.example.thrift.thrift.person;
import com.example.thrift.thrift.personservice;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.layered.TFramedTransport;


/**
 * @Author shu
 * @Description 客服端
 **/
public class ThriftClient {
    public static void main(String[] args) {
        TTransport transport =null;
        try {
            // 连接
            transport = new TFramedTransport(new TSocket("127.0.0.1",8803),600);
            // 协议
            TProtocol protocol = new TCompactProtocol(transport);
            // 调用方法
            personservice.Client client = new personservice.Client(protocol);
            // 打开连接
            transport.open();
            // 调用方法
            person result = client.getPersonInfoByUserNmae("哈哈哈哈");
            System.out.println("Result =: " + result);
        } catch (TException e) {
            e.printStackTrace();
        } finally {
            if (null != transport) {
                transport.close();
            }
        }

    }
}
  • 点入我们自定的方法getPersonInfoByUserNmae,可以看到thrift生成的服务
 public person getPersonInfoByUserNmae(String username) throws personexception, org.apache.thrift.TException
    {
      send_getPersonInfoByUserNmae(username);
      return recv_getPersonInfoByUserNmae();
    }
    

public void send_getPersonInfoByUserNmae(String username) throws org.apache.thrift.TException
    {
      getPersonInfoByUserNmae_args args = new getPersonInfoByUserNmae_args();
      args.setUsername(username);
      // 关键方法,发送数据
      sendBase("getPersonInfoByUserNmae", args);
    }
  • 进入sendBase方法,可以看到他实际调用了TCompactProtocol的实现方法
 protected void sendBase(String methodName, TBase<?,?> args) throws TException {
    sendBase(methodName, args, TMessageType.CALL);
  }

// 将数据写入具体的实现协议中
private void sendBase(String methodName, TBase<?,?> args, byte type) throws TException {
    // 写入开始,协议基本信息
    oprot_.writeMessageBegin(new TMessage(methodName, type, ++seqid_));
    // 写入
    args.write(oprot_);
    // 写入结束
    oprot_.writeMessageEnd();
    // 刷新数据
    oprot_.getTransport().flush();
  }

image.png

 /**将消息头写入线路。紧凑协议消息包含协议版本
   * Write a message header to the wire. Compact Protocol messages contain the
   * protocol version so we can migrate forwards in the future if need be.
   */
  @Override
  public void writeMessageBegin(TMessage message) throws TException {
      // 协议编号
    writeByteDirect(PROTOCOL_ID);
      // 版本
    writeByteDirect((VERSION & VERSION_MASK) | ((message.type << TYPE_SHIFT_AMOUNT) & TYPE_MASK));
      // 序列号
    writeVarint32(message.seqid);
      // 消息名
    writeString(message.name);
  }
  • 生成的 Thrift 对象的通用基本接口:TSerializable
public interface TSerializable {

  /**
   * Reads the TObject from the given input protocol.
   *从协议读取对象
   * @param iprot Input protocol
   */
  public void read(TProtocol iprot) throws TException;

  /**
   * Writes the objects out to the protocol
   *将对象写入协议
   * @param oprot Output protocol
   */
  public void write(TProtocol oprot) throws TException;

}

image.png

  • 显然这调用的是thrift生成的方法
 public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      scheme(oprot).write(oprot, this);
      }

image.png
image.png

  • 调用TCompactProtocol方法开始写入
    public void write(org.apache.thrift.protocol.TProtocol oprot, getPersonInfoByUserNmae_args struct) throws org.apache.thrift.TException {
        struct.validate();
        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.username != null) {
            
          oprot.writeFieldBegin(USERNAME_FIELD_DESC);
            
          oprot.writeString(struct.username);
            
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        
        oprot.writeStructEnd();
      }

    }
  • 与写入方法不同的是,读方法调用的是TSerializabl接口的read实现类,其实也是调用了thrift生成的service中的方法。

image.png

public interface IScheme<T extends TBase> {

  public void read(org.apache.thrift.protocol.TProtocol iproto, T struct) throws org.apache.thrift.TException;

  public void write(org.apache.thrift.protocol.TProtocol oproto, T struct) throws org.apache.thrift.TException;

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长安不及十里

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值