欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

thrift-protocol

程序员文章站 2022-06-17 12:13:58
...

thrift-protocol

// Thrift 消息类型
public final class TMessageType {
  public static final byte CALL  = 1; 		// 调用远程方法,并且期待对方发送响应
  public static final byte ONEWAY = 4; 	// 调用远程方法,不期待响应。即没有步骤3,4
  public static final byte REPLY = 2; 		// 表明处理完成,响应正常返回
  public static final byte EXCEPTION = 3; // 表明出理出错

}

// Thrift 支持的数据类型
public final class TType {
  // 标识属性的结尾(即读到 STOP 表明后边没有属性了)
  public static final byte STOP   = 0;
  
  public static final byte VOID   = 1;
  
  public static final byte BOOL   = 2;   // 对应于 java 中的 boolean
  public static final byte BYTE   = 3;   // byte
  public static final byte DOUBLE = 4;   // double
  public static final byte I16    = 6;   // short
  public static final byte I32    = 8;   // int
  public static final byte I64    = 10;  // long 
  public static final byte STRING = 11;  // String
  // 类似于 C 语言中的结构体
  public static final byte STRUCT = 12;
  
  public static final byte MAP    = 13;
  public static final byte SET    = 14;
  public static final byte LIST   = 15;
  public static final byte ENUM   = 16;
}

// thrift 消息头(方法名称:方法类型:方法序号)
public final class TMessage {
  public final String name;
  public final byte type;
  public final int seqid;
 	// ... 
}

// 字段消息头:字段名称-字段类型-字段序号
public class TField {
  public final String name;
  public final byte   type;
  public final short  id;
}

// List 消息头 元素类型-元素个数
public final class TList {
  public final byte elemType;
  public final int  size;
}

// Map 消息头 键类型-值类型-元素个数
public final class TMap {
  public final byte  keyType;
  public final byte  valueType;
  public final int   size;
}

// Set 消息头 元素类型-元素个数
public final class TSet {
  public final byte elemType;
  public final int  size;
}

// Struct 消息头: XXX_args XXX_result 的消息头说明
public final class TStruct {
  public final String name;
}

TMessage 的 equals 方法比较了 name,而 TField 中没有,想想为什么?

因为在 thrift 中,使用参数类型和索引,区分是哪一个参数。而 TMessage 描述的方法调用的元数据。

string sayBye(1: optional string name, 2: optional i32 age)

TField 的 id 属性,表示是参数相对位置的索引,如下方的 1,2。

struct Request {
        1: required i32 age;
        2: required string name;
}

id 为何是 short 类型?引申为 Java 中参数列表支持多少个参数。
https://zhuanlan.zhihu.com/p/44086976
java 中参数列表最大支持 255 个单位长度。

public abstract class TProtocolDecorator extends TProtocol {
    private final TProtocol concreteProtocol;
    public TProtocolDecorator(TProtocol protocol) {
        super(protocol.getTransport());
        concreteProtocol = protocol;
    }
  	// ...
}

TProtocolDecorator采用装饰者模式,将调用委托给内部的 concreteProtocol。

public class TMultiplexedProtocol extends TProtocolDecorator {
    public static final String SEPARATOR = ":";
    private final String SERVICE_NAME;

    public TMultiplexedProtocol(TProtocol protocol, String serviceName) {
        super(protocol);
        SERVICE_NAME = serviceName;
    }

    @Override
    public void writeMessageBegin(TMessage tMessage) throws TException {
        if (tMessage.type == TMessageType.CALL || tMessage.type == TMessageType.ONEWAY) {
            super.writeMessageBegin(new TMessage(
                    SERVICE_NAME + SEPARATOR + tMessage.name,
                    tMessage.type,
                    tMessage.seqid
            ));
        } else {
            super.writeMessageBegin(tMessage);
        }
    }
}

使用

TSocket transport = new TSocket("localhost", 9090);
transport.open();
TBinaryProtocol protocol = new TBinaryProtocol(transport);
TMultiplexedProtocol mp = new TMultiplexedProtocol(protocol, "Calculator");
Calculator.Client service = new Calculator.Client(mp);
TMultiplexedProtocol mp2 = new TMultiplexedProtocol(protocol, "WeatherReport");
WeatherReport.Client service2 = new WeatherReport.Client(mp2);
System.out.println(service.add(2,2));
System.out.println(service2.getTemperature());
相关标签: thrift

推荐阅读