thrift 基础知识点整理 server protocol transport

奚晟
2023-12-01
Thrift is a cross-language serialization/RPC framework with three major components, protocol, transport, and server. Protocol defines how messages are serialized. Transport defines how messages are communicated between client and server. Server receives serialized messages from the transport, deserializes them according to the protocol and invokes user-defined message handlers, and serializes the responses from the handlers and writes them back to the transport. The modular architecture of Thrift allows it to offer various choices of servers. Here are the list of server available for Java:

Thrift 是一个跨语言的序列化/RPC框架,它含有三个主要的组件:protocol,transport和server


1. protocol

  • TBinaryProtocol : 二进制格式.
  • TCompactProtocol : 压缩格式
  • TJSONProtocol : JSON格式
  • TSimpleJSONProtocol : 提供JSON只写协议, 生成的文件很容易通过脚本语言解析

2. transport

TSocket 阻塞型socket, 用于客户端,采用系统函数read和write进行读写数据;


TServerSocket 非阻塞型socket, 用于服务器端, accecpt到的socket类型都是TSocket(即阻塞型socket);


TBufferedTransport和TFramedTransport都是有缓存的,均继承TBufferBase,调用下一层TTransport类进行读写操作,结构极为相似。只是TFramedTransport以帧为传输单位,帧结构为:4个字节(int32_t)+传输字节串,头4个字节是存储后面字节串的长度,该字节串才是正确需要传输的数据,因此TFramedTransport每传一帧要比TBufferedTransport和TSocket多传4个字节;


TMemoryBuffer继承TBufferBase,用于程序内部通信用,不涉及任何网络I/O,可用于三种模式:(1)OBSERVE模式,不可写数据到缓存;(2)TAKE_OWNERSHIP模式,需负责释放缓存;(3)COPY模式,拷贝外面的内存块到TMemoryBuffer。

TFileTransport直接继承TTransport,用于写数据到文件。对事件的形式写数据,主线程负责将事件入列,写线程将事件入列,并将事件里的数据写入磁盘。这里面用到了两个队列,类型为TFileTransportBuffer,一个用于主线程写事件,另一个用于写线程读事件,这就避免了线程竞争,在读完队列事件后,就会进行队列交换,由于由两个指针指向这两个队列,交换只要交换指针即可。它还支持以chunk(块)的形式写数据到文件。


TFDTransport是非常简单地写数据到文件和从文件读数据,它的write和read函数都是直接调用系统函数write和read进行写和读文件。


TSimpleFileTransport直接继承TFDTransport,没有添加任何成员函数和成员变量,不同的是构造函数的参数和在TSimpleFileTransport构造函数里对父类进行了初始化(打开指定文件并将fd传给父类和设置父类的close_policy为CLOSE_ON_DESTROY)。


TZlibTransport跟TBufferedTransport和TFramedTransport一样,调用下一层TTransport类进行读写操作。它采用<zlib.h>提供的zlib压缩和解压缩库函数来进行压解缩,写时先压缩再调用底层TTransport类发送数据,读时先调用TTransport类接收数据再进行解压,最后供上层处理。

TSSLSocket继承TSocket,阻塞型socket, 用于客户端;采用openssl的接口进行读写数据。checkHandshake()函数调用SSL_set_fd将fd和ssl绑定在一起,之后就可以通过ssl的SSL_read和SSL_write接口进行读写网络数据。

TSSLServerSocket继承TServerSocket,非阻塞型socket, 用于服务器端;accecpt到的socket类型都是TSSLSocket类型。

THttpClient和THttpServer是基于http1.1协议的继承Transport类型,均继承THttpTransport,其中
THttpClient用于客户端,THttpServer用于服务器端。两者都调用下一层TTransport类进行读写操作,均用到TMemoryBuffer作为读写缓存,只有调用flush()函数才会将真正调用网络I/O接口发送数据。

TTransport是所有Transport类的父类,为上层提供了统一的接口而且通过TTransport即可访问各个子类不同实现,类似多态。

3. server

TSimpleServer
TSimplerServer接受一个连接,处理连接请求,直到客户端关闭了连接,它才回去接受一个新的连接。


THsHaServer
使用一个单独的线程来处理网络I/O,一个独立的worker线程池来处理消息,只要有空闲的worker线程,消息就会被立即处理,因此多条消息能被并行处理。


TThreadedSelectorServer允许你用多个线程来处理网络I/O。它维护了两个线程池,一个用来处理网络I/O,另一个用来进行请求的处理。

当网络I/O是瓶颈的时候,TThreadedSelectorServer比THsHaServer的表现要好。



TThreadPoolServer
 有一个专用的线程用来接受连接,一旦接受了一个连接,它就会被放入ThreadPoolExecutor中的一个worker线程里处理。
 worker线程被绑定到特定的客户端连接上,直到它关闭。一旦连接关闭,该worker线程就又回到了线程池中。
 你可以配置线程池的最小、最大线程数,默认值分别是5(最小)和Integer.MAX_VALUE(最大).
 这意味着,如果有1万个并发的客户端连接,你就需要运行1万个线程。所以它对系统资源的消耗不像其他类型的server一样那么“友好”。此外,如果客户端数量超过了线程池中 的最大线程数,在有一个worker线程可用之前,请求将被一直阻塞在那里。

TThreadPoolServer的表现非常优异。在好点的计算机上,它可以支持1万个并发连接而没有任何问题。如果你提前知道了将要连接到你服务器上的客户端数量,并且你不介意运行大量线程的话,TThreadPoolServer对你可能是个很好的选择。






 类似资料: