Java实现Thrift实例
简单的Thrift网络栈图示
+-------------------------------------------+
| Server |
| (single-threaded, event-driven etc) |
+-------------------------------------------+
| Processor |
| (compiler generated) |
+-------------------------------------------+
| Protocol |
| (JSON, compact etc) |
+-------------------------------------------+
| Transport |
| (raw TCP, HTTP etc) |
+-------------------------------------------+
传输层为网络的读写提供了一个简单的抽象。这使得Thrift能够将底层传输与系统的其余部分(例如序列化/反序列化)解耦。
以下是Transport接口暴露的一些方法:
除了上面的Transport接口,Thrift还使用ServerTransport接口来接受或创建原始传输对象。顾名思义,ServerTransport主要用于服务器端,用于为传入连接创建新的Transport对象。
以下是大多数thrift支持的语言可以使用的一些传输:
协议抽象定义了一种将内存中的数据结构映射到有线格式的机制。换句话说,协议规定了数据类型如何使用底层Transport对自身进行编码/解码。因此,协议实现控制编码方案并负责(反)序列化。在这个意义上,协议的一些例子包括JSON、XML、纯文本、压缩二进制等。
有线格式在广义上指的是用于在内存或硬盘上表达数据的格式,“XML/JSON wire format” 是特定物理表达形式(physical representation,实际表达形式)的实例。其中,对于数据的表达格式,如数据类型等进行了规定。XML/JSON wire format描述的是依据W3C相关技术规范所编写的特定消息/文档的物理表达形式。此类格式之中规定的是用于在运行时环境下解析或写入XML/JSON消息/文档的相关信息。
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()
Thrift 协议在设计上面向数据流的。不需要任何明确的框架。例如,在开始序列化之前,我们不需要知道字符串的长度或列表中的items数。大多数支持 Thrift 的语言都可以使用以下协议:
处理器封装了从输入流读取数据和向输出流写入数据的能力。输入和输出流由Protocol对象表示。Processor接口非常简单
interface TProcessor {
bool process(TProtocol in, TProtocol out) throws TException
}
特定于服务的处理器实现由编译器生成。处理器本质上是从连接中读取数据(使用输入协议),将处理委托给处理程序(由用户实现),并通过连接(使用输出协议)写入响应。
服务器汇集了上述所有功能:
Apache Thrift 不支持以下内容:
Thrift类型系统旨在允许程序员尽可能多地使用原生类型,无论他们使用哪种编程语言。此信息基于并取代了Thrift白皮书中的信息。Thrift IDL提供了用于为每种目标语言生成代码的类型的描述。
选择基本类型的目标是简单明了,而不是复杂多样,重点关注所有编程语言中可用的关键类型。
注意没有无符号整数类型。这是因为许多编程语言都没有本地无符号整数类型。
binary: a sequence of unencoded bytes 一个未编码的字节序列
注:目前,这是上述字符串类型的一种特殊形式,是为了更好地与 Java 互操作而添加的。目前的计划是在某个时候将其提升为基本类型。
Thrift 结构定义了一个通用对象–它们本质上等同于 OOP 语言中的类,但没有继承性。结构体有一组强类型字段,每个字段都有一个唯一的名称标识符。字段可以有各种注释(数字字段 ID、可选默认值等),这些注释在Thrift IDL中都有描述。
Thrift 容器是强类型的容器,可以映射到大多数编程语言中常用和可用的容器类型。
有三种容器类型:
容器元素可以是任何有效的 Thrift 类型。
注:为获得最大兼容性,map 的键类型应为基本类型,而不是结构或容器类型。有些语言的本地映射类型不支持更复杂的键类型。此外,JSON 协议只支持基本类型的键类型。
异常在功能上等同于结构体,只不过它们在每种目标编程语言中都继承了原生异常基类,以便与任何特定语言中的本地异常处理无缝集成。
服务使用 Thrift 类型定义。定义服务在语义上等同于在面向对象编程中定义接口(或纯虚拟抽象类)。Thrift 编译器会生成实现接口的功能完备的客户端和服务器存根。
服务由一组命名函数组成,每个函数都有一个参数列表和一个返回类型。
请注意,除了所有其他已定义的 Thrift 类型外,void 也是函数返回的有效类型。此外,还可以在 void 函数中添加单向修饰关键字,这样生成的代码将不会等待响应。请注意,纯 void 函数会向客户端返回一个响应,以保证服务器端的操作已经完成。而单向方法调用只能保证客户端在传输层请求成功。同一客户端的单向方法调用可能会被服务器并行或不按顺序执行。