基本架构
由上篇学习
Apache Thrift学习(2):Thrift使用入门
的demo基本可以得出如下图所示架构:
Your Code代表客户端和服务端的业务代码
XXXService.Client:与服务端连接、通讯的client对象,用于[Service]接口的方法调用。这里的Service指的是Thrift生成的Service接口层
XXX.write()/read():是Thrift生成的代码,write()是向服务端通过socket写数据,read()是从服务端通过socket接收数据。Thrift生成的相关代码如下:
client示例代码如下:
package com.leolee.thrift.person;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TFramedTransport;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
/**
* @ClassName ThriftClient
* @Description: Thrift 客户端
* @Author LeoLee
* @Date 2020/9/6
* @Version V1.0
**/
public class ThriftClient {
public static void main(String[] args) {
//服务端transport用的是TFramedTransport,客户端也要用TFramedTransport
TTransport transport = new TFramedTransport(new TSocket("127.0.0.1", 8899), 60);//对应服务端的传输层方法[TFramed]
TProtocol protocol = new TCompactProtocol(transport);//对应服务端的协议层方法[TCompact]
PersonService.Client client = new PersonService.Client(protocol);
try {
//打开连接
transport.open();
Person person = client.getPersonByName("LeoLee");
System.out.println("打印getPersonByName请求结果:");
System.out.println(person.getName());
System.out.println(person.getAge());
System.out.println(person.isMarried());
System.out.println("------------------------");
Person person2 = new Person();
person2.setName("LeoLee");
person2.setAge(25);
person2.setMarried(false);
client.savePerson(person2);
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
} finally {
transport.close();
}
}
}
这个示例中,
PersonService.Client
对象分别调用了service层的
getPersonByName
和
savePerson
两个方法,以
getPersonByName
为例查看Thrift生成的代码:
一定是存在了
send_xxx()
和
recv_xxx()
,这两个方法一个负责write,一个负责read
send_xxx:
recv_xxx:
最终都会是会调用
TSerializable
的
read
和
write
TProtocol:协议层(应用层),决定以什么样的数据格式来进行数据的传递,强调的是数据的格式。
TTransport:传输层
underlying I/O:实际的网络I/O来传递数据,以字节码的方式在客户端和服务端之间传递
客户端和服务端就是以上面的这个流程,自上而下的执行,互相读写。以上这个架构其实不仅仅限于Thrift,一般的RPC架构都是类似的原理
传输格式
-
TBinaryProtocol:二进制的格式,肯定比文本格式传递数据量小,效率高
-
TCompactProtocol:比TBinaryProtocol的效率更高,将二进制数据进一步压缩为一种“更紧凑”的数据格式
-
TJSONProtocol:文本格式,JSON格式数据
-
TSimpleJSONProtocol:极少使用,提供了JSON只写协议,简单的来讲,这是一种缺少源数据信息的格式,当数据被转化为这种格式后,无法在对端(服务端或者客户端)再反解析为源数据。其内容可以通过脚本语言解析。(
说实话,最后的这个通过脚本语言解析,我也没理解什么鬼,查了一下SimpleJSON,大概是一种无法解析字段数据类型的json格式
)
-
TDebugProtocol:数据调试格式,一种易懂的肉眼可读的文本格式,以便于多端debug(数据传输过程中可抓包截获,分析传递过程中数据的结构等)
数据传输方式
-
TSocket:使用的最少,阻塞式socket
-
TFramedTransport:以frame为单位进行传输,非阻塞式的服务中使用。该传输方式会将传输的数据切分为一个一个的frame
-
TFileTransport:以文件形式传输
-
TMemoryTransport:将内存用于I/O,在Thrift JAVA实现中,内部实际上使用了简单的ByteArrayOutputStream
-
TZlibTransport:使用Zlip对数据进行压缩,与其他传输方式联合使用。当前无JAVA实现。
支持的服务模型
TSimpleServer:简单的单线程服务模型,常用于测试
TThreadPoolServer:多线程服务模型,使用标准的阻塞式IO(类似于一个JAVA的动态线程池,当一个请求到服务端后,会分配一个线程供本次请求使用,当使用完毕后释放,当线程池不够的时候也会创建,同样当有闲置的线程时,也会回收)
TNonblockingServer:多线程服务模型,使用非阻塞IO(需要配合TFrameTransport的数据传输方式)
THsHaServer:THsHa引入了线程池去处理,其模型把读写任务放到线程池处理,提供Half-sync/Half-async的处理模式,Half-sync处理IO事件(accept/read/write io),alf-async用于handler对RPC的同步处理
需要代码的来这里拿嗷:
demo项目地址