Apache Thrift 介绍

Apache Thrift简介

Thrift源于大名鼎鼎的facebook之手,在2007年facebook提交Apache基金会将Thrift作为一个开源项目,对于当时的facebook来说创造thrift是为了解决facebook系统中各系统间大数据量的传 输通信以及系统之间语言环境不同需要跨平台的特性。所以thrift可以支持多种程序语言,例如:  C++, C#, Cocoa, Erlang, Haskell, Java, Ocami, Perl, PHP, Python, Ruby, Smalltalk. 在多种不同的语言之间通信thrift可以作为二进制的高性能的通讯中间件,支持数据(对象)序列化和多种类型的RPC服务。Thrift适用于程序对程 序静态的数据交换,需要先确定好他的数据结构,他是完全静态化的,当数据结构发生变化时,必须重新编辑IDL文件,代码生成,再编译载入的流程,跟其他IDL工具相比较可以视为是Thrift的弱项,Thrift适用于搭建大型数据交换及存储的通用工具,对于大型系统中的内部数据传输相对于JSON和xml无论在性能、传输大小上有明显的优势。

Thrift如何使用

本文基于thrift最新版本0.6.1。

首先呢,Thrift使用了ThriftIDL来定义服务器和客户端的接口。例如,这是本文使用的一个thrift(calculator.thrift)文件。

 

namespace java calculator
 
/*
Thrift的注释与C++或Java类似
*/
 
/*
在这里我们定义了加减乘除的一个枚举类型
*/
enum Operation {
  ADD,
  SUBTRACT,
  MULTIPLY,
  DIVIDE
}
 
/*
Thrift支持自定义的异常
*/
exception InvalidOperation {
  1: i32 errorCode,
  2: string message
}
 
/*
定义一下我们的Service接口
*/
service Calculator {
 
   i32 calculate(1:Operation operation, 2:i32 num1, 3:i32 num2) throws (1:InvalidOperation e),
}
 

 

接下来,我们需要把这个thrift文件编译成Java文件。

我们需要的编译工作可以到http://thrift.apache.org/download/下载:Thrift compiler for Windows (thrift-0.6.1.exe) 。千万不要下载“Snapshot Releases”的,这个不一定能用,我就下错了,结果无法使用,呵呵。

接下来我们运行命令

thrift-0.6.1.exe -o src --gen java calculator.thrift

可以看到在src目录下生成了如下的文件

 

gen-java\calculator\Calculator.java
gen-java\calculator\InvalidOperation.java
gen-java\calculator\Operation.java

 

把这几个文件加入到你的项目中吧。

下面,我们需要thrift的Java库。

使用maven或ivy的可以参考http://mvnrepository.com/artifact/org.apache.thrift/libthrift/0.6.1进行下载

thrift没有提供完整的下载,不过既然是搞Java的,起码要会maven或ivy吧。

实在不行,就去http://svn.apache.org/repos/asf/thrift/trunk/lib/java/下载源代码,然后运行一下ant就ok啦。

到这里我们已经准备好了thrift。

我们看一下thrift的架构

thrift最大的功劳就在于他帮助我们实现了传输层(TTransport)协议层(TProtocol),我们只需要选择需要一个适合自己的实现就ok啦。

例如,我们客户端可以这么写

package calculator;

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;
import org.apache.thrift.transport.TTransportException;

public class Client {

	public static void main(String[] args) {
		// 传输层
		// * TSocket- 使用堵塞式I/O进行传输,也是最常见的模式。
		// * TFramedTransport- 使用非阻塞方式,按块的大小,进行传输,类似于Java中的NIO。
		// * TFileTransport- 顾名思义按照文件的方式进程传输,虽然这种方式不提供Java的实现,但是实现起来非常简单。
		// * TMemoryTransport- 使用内存I/O,就好比Java中的ByteArrayOutputStream实现。
		// * TZlibTransport- 使用执行zlib压缩,不提供Java的实现。
		TTransport transport = new TSocket("localhost", 9090);

		// 协议层
		// * TBinaryProtocol – 二进制编码格式进行数据传输。
		// * TCompactProtocol – 这种协议非常有效的,使用Variable-Length Quantity
		// (VLQ)编码对数据进行压缩。
		// * TJSONProtocol – 使用JSON的数据编码协议进行数据传输。
		// * TSimpleJSONProtocol – 这种节约只提供JSON只写的协议,适用于通过脚本语言解析
		TProtocol protocol = new TBinaryProtocol(transport);

		Calculator.Client client = new Calculator.Client(protocol);

		try {
			transport.open();

			System.out.println(client.calculate(Operation.ADD, 1, 2));
			System.out.println(client.calculate(Operation.SUBTRACT, 3, 5));
			System.out.println(client.calculate(Operation.MULTIPLY, 4, 2));
			System.out.println(client.calculate(Operation.DIVIDE, 1, 0));

		} catch (TTransportException e) {
			e.printStackTrace();
		} catch (InvalidOperation e) {
			e.printStackTrace();
		} catch (TException e) {
			e.printStackTrace();
		} finally {
			// 最后一定要调用close来释放资源
			transport.close();
		}

	}
}


这个客户端很简单,设置一个传输层(TTransport)和协议层(TProtocol)的实现类TSocket和TBinaryProtocol,就可以使用thrift帮我们生成的类alculator.Client(这个完全不用我们写一行代码的,自动生成的类)来调用服务器上的真正的Calculator对象了,用起来跟直接调用函数差不多,把网络传输细节都隐藏起来了。

下面我们看一下服务器的实现。

package calculator;

import org.apache.thrift.TException;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TSimpleServer;
import org.apache.thrift.transport.TServerSocket;
import org.apache.thrift.transport.TServerTransport;
import org.apache.thrift.transport.TTransportException;

public class Server {

	/*
	 * 在服务器这边,由这个类来真正处理客户端的请求。
	 */
	public static class CalculatorHandler implements Calculator.Iface {

		@Override
		public int calculate(Operation operation, int num1, int num2)
				throws InvalidOperation, TException {
			switch (operation) {
			case ADD:
				return num1 + num2;
			case SUBTRACT:
				return num1 - num2;
			case MULTIPLY:
				return num1 * num2;
			case DIVIDE:
				if (num2 == 0) {
					throw new InvalidOperation(1, "divide by zero");
				}
				return num1 / num2;
			default:
				throw new InvalidOperation(0, "impossible code");
			}
		}

	}

	public static void main(String[] args) {

		// 既然是RPC,那么我们在服务器需要有一个真正的类来处理客户端的请求
		Calculator.Processor processor = new Calculator.Processor(
				new CalculatorHandler());

		try {
			TServerTransport serverTransport = new TServerSocket(9090);

			// 服务端类型
			// * TSimpleServer - 单线程服务器端使用标准的堵塞式I/O。
			// * TThreadPoolServer - 多线程服务器端使用标准的堵塞式I/O。
			// * TNonblockingServer – 多线程服务器端使用非堵塞式I/O,并且实现了Java中的NIO通道。
			TServer server = new TSimpleServer(
					new TServer.Args(serverTransport).processor(processor));
			
			server.serve();

			// 跟Client的写法比起来,是不是觉得少了TProtocol?
			// 因为TServer.Args默认设置的TProtocol是TBinaryProtocol,因此就不显示指定了。

		} catch (TTransportException e) {
			e.printStackTrace();
		}

	}
}


服务器的实现也一样,设置一个传输层(TTransport)和协议层(TProtocol)的实现类TSocket和TBinaryProtocol,然后直接调用TServer的serve函数就ok了。之后服务器就挂起等待客户端的请求了。

当然,我们还需要在服务器这边写一个真正的CalculatorHandler实例。这个实例在服务器这边进行真正的计算,然后有TServer自动地把结果传递给client。

Thrift比起protobuf的优点

protobuf也提供了跨语言的数据传输解决方案,但是没有thrift的server和client的功能。使用protobuf实现server和client需要自己编写网络传输的代码(缺少thrift的TTransport和TProtocol这两层的实现)。另外,protobuf只支持c++,python,java,语言数量比较少。Thrift支持C++, C#, Erlang, Haskell, Java, Objective C/Cocoa, OCaml, Perl, PHP, Python, Ruby, and Squeak等各种听过或没听过的语言^_^。当然protobuf优势在于传输的数据比thrift小一些,当然差距不是很大。另外,事实上protobuf完全可以实现server/client功能,从protobuf的service功能可以看出来,不知道为什么google没有实现,而是留给用户去实现。

参考资源

http://www.javabloger.com/article/apache-thrift-architecture.html

http://en.wikipedia.org/wiki/Apache_Thrift

http://thrift.apache.org/

http://wiki.apache.org/thrift/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值