1. 简介
The Apache Thrift software framework, for scalable cross-language services development, combines a software stack with a code generation engine to build services that work efficiently and seamlessly between C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, OCaml and Delphi and other languages.
2. 下载安装thrift
下载地址:https://thrift.apache.org/download
thrift-0.9.3.tar.gz [PGP] [MD5]
Thrift compiler for Windows (thrift-0.9.3.exe) [PGP] [MD5]
2.1 如果是Maven构建项目的,直接在pom.xml 中添加如下:
<dependency>
<groupId>org.apache.thrift</groupId>
<artifactId>libthrift</artifactId>
<version>0.9.3</version>
</dependency>
2.2 在linux上安装,通过wget或手动下载源码包进行编译安装:
tar -xvf thrift-0.9.3.tar.gz
cd thrift-0.9.3
./configure
make && make install
# 主要构建thrift需要cpp cpp++ ant等相关依赖包,需要进行安装
2.3 windowns下载thrift-0.9.3.exe便可以通过命令使用
3. 热身的小栗子
这个例子演示一个简单的multiplication service:
3.1 创建 IDL文件.thrift file ,这里是multiplication.thrift,内容如下:
namespace java tutorial
namespace py tutorial
typedef i32 int // We can use typedef to get pretty names for the types we are using
service MultiplicationService
{
int multiply(1:int n1, 2:int n2),
}
3.2 thrift生成代码
使用thrift编译器执行以下命令生成所需语言的代码
格式:(thrift --gen <language> <Thriftfilename>)
thrift --gen java multiplication.thrift
# windows下执行:thrift-0.9.3.exe --gen java multiplication.thrift
执行完成后在当前目录下生成gen-java目录,里面生成了tutorial/MultiplicationService.java文件
3.3 编写MultiplicationServiceImpl.java实现类
需要实现MultiplicationService.Iface接口,由thrift自动生成的代码
import org.apache.thrift.TException;
public class MultiplicationServiceImpl implements MultiplicationService.Iface {
@Override
public int multiply(int n1, int n2) throws TException {
System.out.println("Multiply(" + n1 + "," + n2 + ")");
return n1 * n2;
}
}
3.4 编写thrift MultiplicationServer
以下是实现代码,值得注意的是有关server实现的唯一的事情就是processor类的用法是由thrift自动生成。该processor做两件简单的事情。从输入流中读取数据,并写入数据到输出流。processor从输入读取数据,处理该数据(实际使用由用户自定义service实现来处理数据的)和处理后的数据的写入到输出流。
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TServer.Args;
import org.apache.thrift.server.TSimpleServer;
import org.apache.thrift.transport.TServerSocket;
import org.apache.thrift.transport.TServerTransport;
public class MultiplicationServer {
public static MultiplicationServiceImpl service;
public static MultiplicationService.Processor processor;
public static void main(String[] args) {
try {
service = new MultiplicationServiceImpl();
processor = new MultiplicationService.Processor(service);
Runnable simple = new Runnable() {
public void run() {
simple(processor);
}
};
new Thread(simple).start();
} catch (Exception x) {
x.printStackTrace();
}
}
public static void simple(MultiplicationService.Processor processor) {
try {
TServerTransport serverTransport = new TServerSocket(8090);
TServer server = new TSimpleServer(new Args(serverTransport).processor(processor));
System.out.println("Starting the simple server...");
server.serve();
} catch (Exception e) {
e.printStackTrace();
}
}
}
3.5 编写thrift MultiplicationClient
以下是实现代码,注意对于序列化和反序列化的部分使用的是TBinaryProtocol。我们还可以使用TCompactProtocol , TJSONProtocol,TSimpleJSONProtocol或thrift支持的任何其他协议。有关协议的更多详细信息,请参考thrift协议栈部分内容。
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
public class MultiplicationClient {
public static void main(String [] args) {
try {
TTransport transport = new TSocket("localhost", 8090);
transport.open();
TProtocol protocol = new TBinaryProtocol(transport);
MultiplicationService.Client client = new MultiplicationService.Client(protocol);
perform(client);
transport.close();
} catch (TException x) {
x.printStackTrace();
}
}
private static void perform(MultiplicationService.Client client) throws TException
{
int product = client.multiply(2,4);
System.out.println("2*4=" + product);
}
}
4. 备注
通过从网上其他资料整理出来的一些有用信息,参考的网址:
https://thrift.apache.org/tutorial/java
http://www.micmiu.com/soa/rpc/thrift-sample/
http://www.blogjava.net/ldwblog/archive/2014/12/03/421011.html
4.1 基础架构
thrift的协议栈整体的架构,thrift是一个客户端和服务器端的架构体系(c/s),在最上层是用户自行实现的业务逻辑代码。第二层是由thrift编译器自动生成的代码,主要用于结构化数据的解析,发送和接收。TServer主要任务是高效的接受客户端请求,并将请求转发给Processor处理。Processor负责对客户端的请求做出响应,包括RPC请求转发,调用参数解析和用户逻辑调用,返回值写回等处理。从TProtocol以下部分是thirft的传输协议和底层I/O通信。TProtocol是用于数据类型解析的,将结构化数据转化为字节流给TTransport进行传输。TTransport是与底层数据传输密切相关的传输层,负责以字节流方式接收和发送消息体,不关注是什么数据类型。底层IO负责实际的数据传输,包括socket、文件和压缩数据流等。
协议层TProtocol
在传输协议上总体上划分为文本(text)和二进制(binary)传输协议, 为节约带宽,提供传输效率,一般情况下使用二进制类型的传输协议为多数。
1>TBinaryProtocol – 二进制编码格式进行数据传输。
2>TCompactProtocol – 高效的编码方式,使用类似于protobuffer的Variable-Length Quantity (VLQ) 编码(可以节省传输空间,使数据的传输效率更高)对数据进行压缩。 关于VLQ了解更多(http://en.wikipedia.org/wiki/Variable-length_quantity)
3>TJSONProtocol – 使用JSON的数据编码协议进行数据传输。
4>TSimpleJSONProtocol – 这种节约只提供JSON只写的协议,适用于通过脚本语言解析
5>TDebugProtocol – 在开发的过程中帮助开发人员调试用的,以文本的形式展现方便阅读。
传输层TTransport
1>TSocket- 使用阻塞式I/O进行传输,也是最常见的模式。
2>TFramedTransport- 使用非阻塞方式,按块的大小,进行传输,类似于Java中的NIO。
3>TFileTransport- 顾名思义按照文件的方式进程传输,虽然这种方式不提供Java的实现,但是实现起来非常简单。
4>TMemoryTransport- 使用内存I/O,就好比Java中的ByteArrayOutputStream实现。
5>TZlibTransport- 使用执行zlib压缩,不提供Java的实现。
6>TNonblockingTransport-使用非阻塞方式,用于构建异步客户端。
服务端类型 :
1>TSimpleServer - 单线程服务器端使用标准的阻塞式I/O。
2>TThreadPoolServer - 多线程服务器端使用标准的阻塞式I/O。
3>TNonblockingServer – 多线程服务器端使用非阻塞式I/O,并且实现了Java中的NIO通道。