首页 > 其他分享 >基于注解注册连接的Thrift框架(03)——TProtocol

基于注解注册连接的Thrift框架(03)——TProtocol

时间:2024-07-18 14:45:06浏览次数:13  
标签:03 struct TProtocol args write _. add iprot Thrift

前情提要

之前介绍了TProcessor的同步和异步实现,也说明了TAsyncMethodCall中的状态循环以及它是如何和TServer进行交互的。

TProtocol

TProtocol 是一个抽象类,主要做了两件事情:

  • 绑定一个TTransport
  • 定义一系列读写消息的编解码接口。包括两类,一类是复杂数据结构比如readMessageBegin, readMessageEnd, writeMessageBegin, writMessageEnd.还有一类是基本数据结构,比如readI32, writeI32, readString, writeString

Schema

在编译完IDL之后,会生成一系列“方法名_args”/“方法名_result”的静态类,比如我有一个“add”方法。我就会生成add_argsadd_result 两个类。
Client中可以直接看到对这两个类的实例化:

public void send_add(int arg1, int arg2) throws TException
{
	  add_args args = new add_args();  // 这里
	  args.setArg1(arg1);
	  args.setArg2(arg2);
	  sendBase("add", args);
}

回到静态类中,这里以add_args为例子,可以看到里面有一个静态代码块,初始化了两个Schema。

public static class add_args implements org.apache.thrift.TBase<add_args, add_args._Fields>, java.io.Serializable, Cloneable, Comparable<add_args>   {
	//...
	private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
	static {
		schemes.put(StandardScheme.class, new add_argsStandardSchemeFactory());  // 1、标准Schema
		schemes.put(TupleScheme.class, new add_argsTupleSchemeFactory());  // 2、元组Schema
	}
	//...
}

在 TProtocol 中,返回的是 StandardSchema.class ,只有在 TTupleProtocol 中才进行了重写。所以除了 TTupleProtocol 外,所有的都使用 StandardSchema .

所以,在add_args中,read/write方法的调用最终是调用Schema中的read/write实现。

读写

Thrift对TProtocol的约束中,(调用方)写步骤如下:

1、先writeMessageBegin表示开始传输消息了,写消息头。Message里面定义了方法名,调用的类型,版本号,消息seqId。
2、接下来是写方法的参数,实际就是写消息体。先写入结构:writeStructBegin
3、再写入字段:writeFieldBegin
3.1、再写入内容:如果是集合类型那就writeMapBegin/writeListBegin;如果是一般类型,那就是writeI32/writeI64
3.2、结束字段写入:writeFieldEnd
4、重复第3步骤,把方法中所有的形参都写完之后,writeFieldStop
5、结束结构的写入:writeStructEnd
6、结束消息的传输:writeMessageEnd

// add_args.write()
public void write(org.apache.thrift.protocol.TProtocol oprot, add_args struct) throws TException {
	struct.validate();

	oprot.writeStructBegin(STRUCT_DESC); // 2
	oprot.writeFieldBegin(ARG1_FIELD_DESC);  //3
	oprot.writeI32(struct.arg1); // 3.1
	oprot.writeFieldEnd();  // 3.2
	oprot.writeFieldBegin(ARG2_FIELD_DESC);  // 3
	oprot.writeI32(struct.arg2);  // 3.1
	oprot.writeFieldEnd();  // 3.2
	oprot.writeFieldStop();  // 4
	oprot.writeStructEnd();  // 5
}

(接收方)读信息的过程和(调用方)写入的过程一致:

public void read(org.apache.thrift.protocol.TProtocol iprot, add_args struct) throws TException {
  org.apache.thrift.protocol.TField schemeField;
  iprot.readStructBegin();  // 2
  while (true)
  {
    schemeField = iprot.readFieldBegin();  // 3
    if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
      break;
    }
    switch (schemeField.id) {
      case 1: // 形参1
        if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
          struct.arg1 = iprot.readI32();  // 3.1
          struct.setArg1IsSet(true);
        } else { 
          org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
        }
        break;
      case 2: // 形参2
        if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
          struct.arg2 = iprot.readI32();  // 3.1
          struct.setArg2IsSet(true);
        } else { 
          org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
        }
        break;
      default:
        org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
    }
    iprot.readFieldEnd();  // 4
  }
  iprot.readStructEnd();  // 5
  struct.validate();
}

调用流程

image

整体的调用流程如上图所示,从之前的代码中我们可以知道,在add_argsadd_result中读写都是一一对应的。
从流程中我们可以知道,在客户端和服务端各自调用一边的读和一边的写,从而进行交互。

不同的实现类

上面我们知道了TProtocol的作用、读写的源码以及交互的调用流程。这里介绍TProtocol的实现类。
不同的实现类代表着不同的数据编码:
TJSONProtocol

@Override
public void writeI16(short i16) throws TException {
	writeJSONInteger((long)i16);
}
==============
private void writeJSONInteger(long num) throws TException {
	context_.write();
	String str = Long.toString(num);
	boolean escapeNum = context_.escapeNum();
	if (escapeNum) {
		trans_.write(QUOTE);
	}
	try {
		byte[] buf = str.getBytes("UTF-8");
		trans_.write(buf);
	} catch (UnsupportedEncodingException uex) {
		throw new TException("JVM DOES NOT SUPPORT UTF-8");
	}
	if (escapeNum) {
		trans_.write(QUOTE);
	}
}

把他们都转化成JSON格式。
TJSONProtocol

@Override
public void writeI16(short i16) throws TException {
	writeJSONInteger((long)i16);
}
==============
private void writeJSONInteger(long num) throws TException {
	context_.write();
	String str = Long.toString(num);
	boolean escapeNum = context_.escapeNum();
	if (escapeNum) {
		trans_.write(QUOTE);
	}
	try {
		byte[] buf = str.getBytes("UTF-8");
		trans_.write(buf);
	} catch (UnsupportedEncodingException uex) {
		throw new TException("JVM DOES NOT SUPPORT UTF-8");
	}
	if (escapeNum) {
		trans_.write(QUOTE);
	}
}

TBinaryProtocol

public void writeI16(short i16) throws TException {
	i16out[0] = (byte)(0xff & (i16 >> 8));
	i16out[1] = (byte)(0xff & (i16));
	trans_.write(i16out, 0, 2);
}

标签:03,struct,TProtocol,args,write,_.,add,iprot,Thrift
From: https://www.cnblogs.com/cybersiren/p/18309361

相关文章

  • 吴恩达深度学习课程笔记Lesson03
    第三周:浅层神经网络(Shallowneuralnetworks)文章目录第三周:浅层神经网络(Shallowneuralnetworks)3.1神经网络概述(NeuralNetworkOverview)3.2神经网络的表示(NeuralNetworkRepresentation)3.3计算一个神经网络的输出(ComputingaNeuralNetwork'soutput)3.4多样......
  • [1036] Extracting hyperlink information from an Excel file
    Certainly!ExtractinghyperlinkinformationfromanExcelfile(specifically.xlsxformat)inPythoncanbedoneusingtheopenpyxllibrary.Let’sdiverightin:Usingopenpyxl:First,makesureyouhavetheopenpyxllibraryinstalled.Ifnot,youcan......
  • [1035] Extract the content from online PDF file or PDF url
    Certainly!WhenworkingwithonlinePDFsusingthepyPDF2libraryinPython,youcanretrievethecontentfromaPDFfilehostedataURL.Let’sexploreacoupleofwaystoachievethis:Usingrequests(Python3.xandhigher):Ifyou’reusingPython3.x......
  • [题解]P1452 【模板】旋转卡壳 | [USACO03FALL] Beauty Contest G
    P1452【模板】旋转卡壳|[USACO03FALL]BeautyContestG旋转卡壳模板题。凸包用的是Andrew算法,就不详述了,具体可以查查资料了解,但提一嘴Andrew算法的一些细节问题:Andrew算法的一些细节Andrew算法的模板代码如下:sort(a+1,a+1+n,cmp);st[++top]=1;for(inti=2;i<=n;i++){ ......
  • 记录一次在欧拉(openEuler22.03LTS-SP4)系统下安装(踩坑)Freeswitch1.10.11的全过程
    目录前言安装环境1.下载Freeswitch1.1gitclone下载freeswitch库1.2官网下载2.开始安装前的工作2.1安装编译时需要的环境【先安装这个!】2.2configure前需要安装的库2.2.1.spandsp2.2.2.sofia-sip2.2.3.libks2.2.4.signalwire-c2.2.5x2642.2.6.libav2.2.6.1可能出现......
  • 03-函数
    DAY-04课堂笔记函数print()在控制台输出input()获取控制台输⼊的内容type()获取变量的数据类型len()获取容器的⻓度(元素的个数)range()⽣成⼀个序列[0,n)#函数可以实现⼀个特定的功能我们学习⾃⼰如何定义函数,实现特定的功能???函数:将多⾏代码(可以实......
  • 题解 P1031 [NOIP2002 提高组] 均分纸牌
    link贪心题中描述每一堆牌只能移动若干张牌到相邻的牌堆上确定了局部最优解必定能推导出全局最优解。易知均分完后,每堆牌的数量都为纸牌总数的平均数\(\mathrm{arg}\)。所以我们可以预处理每堆牌跟\(\mathrm{arg}\)的差距for(inti=1;i<=n;++i)sum+=a[i];......
  • 宝塔面板申请 Let's Encrypt证书报错:Invalid version. The only valid version for X5
    原因是由于服务器端使用了不兼容的OpenSSL版本导致的,服务器端的X509Req版本只支持0,而宝塔这边默认的版本为2。第一种1、修改/www/server/panel/class下面的acme_v2.py文件搜索找到X509Req.set_version(2)代码段,将其改为X509Req.set_version(0)2、重启宝塔面板服......
  • 黑马头条(day03)
    目录1)自媒体环境搭建1.1)后台搭建1.2)前台搭建 2)自媒体素材管理2.1)素材上传2.2.1)需求分析2.2.2)表结构2.2.3)实现思路2.2.4)接口定义2.2.5)集成heima-file-starter2.2.6)具体实现2.2)素材列表查询2.2.1)接口定义2.2.2)功能实现3)自媒体文章管理3.1)查询所有频道3.1.1)需求......
  • Java语言基础-03
    1.Scanner接收用户输入的数据:packageday04;importjava.util.Scanner;//1.导入一个扫描仪//Scanner的演示publicclassScannerDemo{publicstaticvoidmain(String[]args){//创建类CommandBySwitch,接收用户输入的命令command(int),并输出......