@Yano
2018-12-01T10:34:53.000000Z
字数 3113
阅读 3056
Java
工作中用到Thrift,一直想深入研究一下。今天这篇博客以提问的方式,分析Thrift的源码。文章部分参考自:Thrift源码分析。
本来计划的题目是:「Thrift RPC 源码分析」,可是写了两个小时才发现,我根本没有贴出多少源码……因为我是在公司项目源码中直接分析的,又不能直接贴在博客中,遂放弃 o_0
官方文档 Apache Thrift - Concepts详细说明了Thrift的架构:
+-------------------------------------------+
| Server |
| (single-threaded, event-driven etc) |
+-------------------------------------------+
| Processor |
| (compiler generated) |
+-------------------------------------------+
| Protocol |
| (JSON, compact etc) |
+-------------------------------------------+
| Transport |
| (raw TCP, HTTP etc) |
+-------------------------------------------+
The Transport layer provides a simple abstraction for reading/writing from/to the network. This enables Thrift to decouple the underlying transport from the rest of the system (serialization/deserialization, for instance).
Transport layer
提供了一个从网络IO读写的简单抽象,可以使Thrift与底层解耦。
Transport接口有:
除了Transport接口,还有一个ServerTransport
,用来在server端创建请求的连接。
Protocol
定义了传输数据的序列化、反序列化机制(JSON、XML、binary、compact binary等)。
Protocol的接口如下:
writeMessageBegin(name, type, seq)
writeMessageEnd()
writeStructBegin(name)
writeStructEnd()
writeFieldBegin(name, type, id)
writeFieldEnd()
writeFieldStop()
writeMapBegin(ktype, vtype, size)
writeMapEnd()
writeListBegin(etype, size)
writeListEnd()
writeSetBegin(etype, size)
writeSetEnd()
writeBool(bool)
writeByte(byte)
writeI16(i16)
writeI32(i32)
writeI64(i64)
writeDouble(double)
writeString(string)
name, type, seq = readMessageBegin()
readMessageEnd()
name = readStructBegin()
readStructEnd()
name, type, id = readFieldBegin()
readFieldEnd()
k, v, size = readMapBegin()
readMapEnd()
etype, size = readListBegin()
readListEnd()
etype, size = readSetBegin()
readSetEnd()
bool = readBool()
byte = readByte()
i16 = readI16()
i32 = readI32()
i64 = readI64()
double = readDouble()
string = readString()
Processor
封装了读取输入流、写入输出流的能力,其中输入流、输出流都是Protocol
的对象。接口很简单:
interface TProcessor {
bool process(TProtocol in, TProtocol out) throws TException
}
其中用户需要实现TProcessor接口。
TTransport有很多实现,其中最重要的就是TFramedTransport。
客户端的实际使用:
TSocket socket = new TSocket(host, port);
socket.setTimeout(timeout);
TTransport transport = new TFramedTransport(socket);
TProtocol protocol = new TCompactProtocol(transport);
transport.open();
Thrift主要支持的协议有:
其中Binary
协议的序列化、反序列化,可以参考我的另一篇文章:Thrift 对象序列化、反序列化-字节数组分析。
解释起来太麻烦,还是直接贴思维导图吧,更直观 0_o
TServerTransport作为服务器的Acceptor抽象,来监听端口,创建客户端Socket连接。