Thrift介绍
由于我们组要求使用的是Thrift0.8.0版本,下面以这个版本为例来讲解如何安装配置Thrift。
一、安装
下载地址:http://archive.apache.org/dist/thrift/0.8.0/thrift-0.8.0.tar.gz
二、Thrift简介
Thrift是一个轻量级的、跨语言的远程服务调用框架。Thrift支持不同的编程语言,包括C++、Java、Python、PHP、Ruby等。
三、Thrift软件栈
Thrift软件栈从下到上依次是:传输层、协议层、处理层和服务层。
传输层:TTransport,负责直接从网络读取和写入数据,定义了具体的网络传输协议,比如TCP/IP等;
协议层:TProtocal,定义了数据传输格式,负责网络传输数据的序列化和反序列化,比如说json、XML、二进制数据等;
处理层:TProcessor,处理层是由具体的IDL(接口描述语言)生成的,封装了具体的底层网络传输和序列化方式,并委托给用户实现的handler进行处理;
服务层:TServer,整合上述组件,提供具体的网络线程/IO模型,形成最终的服务,然后接收Client的请求,并转到某个TProcessor上进行请求处理。
Thrift的传输层
创建的传输层有以下几种:
TSocket:使用阻塞式IO进行传输,是最常见的模式;
TNonblockingTransport:使用非阻塞方式,用于构建异步客户端
TFramedTransport:使用非阻塞方式,按块的大小进行传输,类似于
Java
中的NIO
。TBufferedTransport:对某个Transport对象操作的数据进行buffer,即从buffer中读取数据进行传输,或者将数据直接写入buffer。
THttpTransport:采用Http传输协议进行数据传输。
TFileTransport:文件(日志)传输类,允许client将文件传给server,允许server将收到的数据写到文件中。
TZlibTransport:与其他的TTransport配合使用,压缩后对数据进行传输,或者将收到的数据解压
Thrift的服务端类型
TSimpleServer:单线程服务器端,使用标准的阻塞式
I/O
,只在演示的时候用,实际工作中很少用到;TThreadPoolServer:多线程服务器端,使用标准的阻塞式
I/O
,主线程负责监听新连接,其他处理交给单独的线程池;TNonblockingServer:单线程服务器端,使用非阻塞式
I/O
,一个线程循环处理监听socket,处理连接,读,写请求;THsHaServer:半同步半异步服务器端,基于非阻塞式
IO
读写和多线程工作任务处理,对TNonblockingServer的优化,读请求以及后续的业务处理交给单独的线程池来做;TThreadedSelectorServer:多线程选择器服务器端,对
THsHaServer
在异步IO
模型上进行增强,最高级的模式,大部分场景下性能都不会差,如果不知道选哪个就选这个。
四、Thrift数据类型
Thrift主要有下面5种类型:
1. 基本类型:
bool: 布尔值
byte: 8位有符号整数
i16: 16位有符号整数
i32: 32位有符号整数
i64: 64位有符号整数
double: 64位浮点数
string: UTF-8编码的字符串
binary: 二进制串
注意:Thrift不支持无符号整型,因为很多编程语言本身就不存在无符号整型,如java。
2. 结构体类型:
struct: 定义的结构体对象
3. 容器类型:
list: 有序元素列表
set: 无序无重复元素集合
map: 有序的key/value集合
4. 异常类型:
exception: 异常类型
5. 服务类型:
service: 具体对应服务的类
此外thrift还支持常量和枚举。
五、Thrift实战
5.1 编写IDL文件
hello.thrift
5.2 编译IDL文件生成Java文件
于未指定代码生成的目标目录,生成的类文件默认存放在gen-java
目录下。这里会生成4个重要的内部接口/类:
Iface:服务端通过实现
HelloWorldService.Iface
接口,向客户端的提供具体的同步业务逻辑。AsyncIface:服务端通过实现
HelloWorldService.Iface
接口,向客户端的提供具体的异步业务逻辑。Client:客户端通过
HelloWorldService.Client
的实例对象,以同步的方式访问服务端提供的服务方法。AsyncClient:客户端通过
HelloWorldService.AsyncClient
的实例对象,以异步的方式访问服务端提供的服务方法。
5.3 代码实现
新建maven工程,pom中添加依赖
将生成的HelloWorldService.java
源文件拷贝进项目源文件目录中,并实现HelloWorldService.Iface
的定义的say()
方法。
HelloWorldServiceImpl.java
服务端实现:SimpleServer.java
客户端实现:SimpleClient.java
依次运行服务端和客户端会出现以下结果:
5.4 总结
从使用thrift的过程中可以总结thrift实现服务端和客户端逻辑的基本思路。
Thrift实现服务端:
实现服务处理接口impl
创建TProcessor
创建TServerTransport
创建TProtocol
创建TServer
启动Server
Thrift实现客户端:
创建Transport
创建TProtocol
基于TTransport和TProtocol创建Client
六、遇到的问题
1. 运行时报错Class JavaLaunchHelper is implemented in both...
【错误描述】
idea run服务端的时候报错:objc[79886]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home/bin/java (0x106b914c0) and /Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home/jre/lib/libinstrument.dylib (0x108e7e4e0). One of the two will be used. Which one is undefined.
【问题解决】
这是Mac版idea的一个bug,jdk1.8及以上已经修复了,因为项目要求是jdk1.7,并且这个错误不影响正常使用可以忽略不计了。
2. 启动server时报错SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
【错误描述】
启动server的时候报错:
【问题解决】
上面的意思是,在运行时,你没有做日志的实现(或者说日志的绑定),所以slf4j简简单单的使用了一个什么也不会做的空实现。 为了看到正确的输出,你应该尝试使用一个简单(simple)的实现,这个实现根本不需要任何配置!只要回到pom.xml然后添加如下配置:
参考:
【thrift概述与入门】https://juejin.im/post/6844903622380093447
【thrift基本原理】https://www.jianshu.com/p/5e3a4ab838a3
Last updated