thrift中的概念

Thrift的网络栈

Apache Thrift的网络栈的简单表示如下:

  +-------------------------------------------+
  | Server                                    |
  | (single-threaded, event-driven etc)       |
  +-------------------------------------------+
  | Processor                                 |
  | (compiler generated)                      |
  +-------------------------------------------+
  | Protocol                                  |
  | (JSON, compact etc)                       |
  +-------------------------------------------+
  | Transport                                 |
  | (raw TCP, HTTP etc)                       |
  +-------------------------------------------+

Transport (传输)

传输层提供了一个用于向网络读写的简单抽象. 通过这种方式, thrift可以将下层的传输协议与thrift上层的其他部分((例如序列化和反序列化)分离.

下面是Transport接口提供的一些方法:

(1) open

(2) close

(3) read

(4) write

(5) flush

除了上面的Transport接口, Thrift还使用ServerTransport接口来接受或者生成基本的transport对象. 正如名字所建议的, ServerTransport主要用在服务端为新来的连接创建新的 Transport对象. 提供的方法如下:

(1) open

(2) listen

(3) accept

(4) close

绝大多数thrift支持的语言都可用的transport如下:

(1) file: 从硬盘中读写文件

(2) http: http网络通信

 

Protocol (协议)

Protocol用来定义内存中的数据结构如何使用下层的Transport来序列化和反序列化自身. 所以protocol实现用来控制编码模式, 以及用于序列化和反序列化. protocol的一些实例包括JSON, XML, plain text, 紧凑的二进制编码等.

下面是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 Protocols是面向字节流设计的. 这里不需要进行显式的分片. 例如, 我们在序列化时, 不需要知道字符串的长度, 也不需要知道list的元素个数. 对于绝大多数thrift支持的语言都支持的Protocol(协议)有:

(1) binary: 很简单的二进制编码, 现将成员的长度和类型编码成字节, 然后跟上成员的实际值

(2) 紧凑的编码格式 (参考 https://issues.apache.org/jira/browse/THRIFT-110)

(3) json格式

 

Processor (处理单元)

一个Processor用来封装从输入流读取数据和向输出流写入数据的能力. 输入流和输出流使用Protocol对象来表示. Processor的接口很简单:

interface TProcessor {
    bool process(TProtocol in, TProtocol out) throws TException
}

服务端特定的processor实现由编译器生成. Processor所做的是从输入protocol中读取数据, 然后将这些数据转交给handler(具体处理单元, 用户实现), 然后再将结果写入到输出protocol中.

 

Server

Server用来将上述特征聚集到一起:

(1) 创建一个基于Handler的Processor

(2) 创建一个transport

(3) 创建输入和输出协议(protocol)

基于上面的组员, 创建一个Server, 然后Server调用serve函数, 等待连接, 然后对请求进行处理.

参考示例 (C++):

class SharedServiceHandler : virtual public SharedServiceIf {
 public:
  SharedServiceHandler() {
    // Your initialization goes here
  }

  void getStruct(SharedStruct& _return, const int32_t key) {
    // Your implementation goes here
    printf("getStruct\n");
  }

};

int main(int argc, char **argv) {
  int port = 9090;
  shared_ptr<SharedServiceHandler> handler(new SharedServiceHandler());
  shared_ptr<TProcessor> processor(new SharedServiceProcessor(handler));
  shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
  shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
  shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());

  TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);
  server.serve();
  return 0;
}

 

上一篇:《精通并发与Netty》学习笔记(07 - 基于Thrift实现Java与Python的RPC调用)


下一篇:thrift接口描述语言 (基于thrift 0.13.0版本)