架构设计:系统间通信(12)——RPC实例Apache Thrift 中篇

本文详细探讨了Apache Thrift的内部机制,包括其消息格式如TBinaryProtocol和TCompactProtocol的优缺点,以及如何利用这些协议实现高效的数据序列化。此外,文章还讨论了Thrift支持的阻塞和非阻塞IO模型以及线程池在处理客户端请求中的作用。通过理解这些关键要素,可以更好地理解Apache Thrift为何能在RPC框架中表现出高性能。
摘要由CSDN通过智能技术生成

(接上文《架构设计:系统间通信(11)——RPC实例Apache Thrift 上篇》)

3、Aapche Thrift详解

在《架构设计:系统间通信(10)——RPC的基本概念》一文中,我专门介绍了一款RPC规范的具体实现中哪些要素和性能息息相关。包括了RPC通讯采用的数据封装格式、RPC通讯采用的网络IO模型和RPC所采用的请求处理方式。这个小节我们对Apache Thrift中的这三个要素,这样读者就可以知晓为什么Apache Thrift的性能如此高效了。

3-1、Aapche Thrift与消息格式

Apache Thrift支持多种消息格式封装。这些消息格式是如果进行编码和解码的是不需要使用者关心的,只需要根据自己的需要制定不同的消息封装格式即可。Apache Thrift所有消息格式封装的实现,都继承与TProtocol这个抽象类,如下图所示:

这里写图片描述

3-1-1、TBinaryProtocol

二进制流的编码格式。由于需要支持跨语言,所以Apache Thrift支持有限的几种通用类型,包括基本类型(Float、Double、Integer、Long、String、Short)、集合类型(Map、Set、List)还有Pojo类型(实际上就是前两者若干类型的组合形式)。

那么这个类所生成的二进制流和传统的java序列化后生成的二进制流有什么样的区别(或者是优势)呢?我们可以通过阅读TBinaryProtocol的源代码进行研究。

我们以TBinaryProtocol中,对Integer的序列化过程进行详细的解释,来对比java提供的其他几种序列化的方式找到不同。首先java中,如果要将一个Integer对象通过网络发送出去,要做的第一件事情就是序列化,那么我们常用的序列化方式有两种,如下所示:

  • java中序列化Integer对象的第一种方法:
Integer integerObject = 10066329;
integerObject.toString().getBytes();
  • java中序列化Integer对象的第二种方法:
ByteArrayOutputStream aStream = new ByteArrayOutputStream();
ObjectOutputStream oStream = new ObjectOutputStream(aStream);
oStream.writeObject(integerObject);
aStream.toByteArray();

第一种方式是将Integer对象中的值序列化;第二种方式,是将Integer整个对象序列化。这两种方式虽然都产生byte[],实际上性质是完全不一样的。我们来看一下这两种方式产生的byte[]的内容:

  • 序列化Integer的值:

[49, 48, 48, 54, 54, 51, 50, 57]

  • 序列化整个Integer对象:

[-84, -19, 0, 5, 115, 114, 0, 17, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 73, 110, 116, 101, 103, 101, 114, 18, -30, -96, -92, -9, -127, -121, 56, 2, 0, 1, 73, 0, 5, 118, 97, 108, 117, 101, 120, 114, 0, 16, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 78, 117, 109, 98, 101, 114, -122, -84, -107, 29, 11, -108, -32, -117, 2, 0, 0, 120, 112, 0, -103, -103, -103]

第一种方式序列化后,byte数组有8个byte元素(因为是首先转换成字符串的,所以实际上这个大小会随着Integer值的大小增加而增加);第二中方式序列化后,byte数组一共有 > 20 个byte元素,其中除了记录Integer的值以外,还包括描述这个类型的其他属性。

那么我们再来看看TBinaryProtocol中,是如何序列化Integer类型的。首先我们来看一下TBinaryProtocol进行Integer序列化的这部分源代码,如下图所示:

private byte[] i32out = new byte[4];
public void writeI32(int i32) throws TException {
    i32out[0] = (byte)(0xff & (i32 >> 24));
    i32out[1] = (byte)(0xff & (i32 >> 16));
    i32out[2] = (byte)(0xff & (i32 >> 8));
    i32out[3] = (byte)(0xff
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值