天天看点

Apache Thrift原理及windows使用

本文旨在全面的介绍thrift的使用流程,

使用的例子为一个简单的加法服务程序,从客户端发送请求及操作数,服务器端返回加法结果

一、安装篇:

windows:

1. 直接下载windows版本的thrift编译器,http://archive.apache.org/dist/thrift/0.9.0/thrift-0.9.0.exe  

下载完成后,将其改名为thrift,并将安装路径添加到系统环境变量PATH中。

2. 下载相应的源码,生成jar包  (详细过程:http://f.dataguru.cn/thread-68637-1-1.html)

注意:thrift编译器的版本必须与相应的jar包版本相同。在windows下生成jar包比较麻烦,此处提供0.9.0版本的jar包供大家使用,上步中下载的编译器也为0.9.0版本

url:

3. 下载org.apache.http及org.apache.commons.logging

http://commons.apache.org/proper/commons-logging/download_logging.cgi

http://hc.apache.org/downloads.cgi

4. 下载slf4j jar包

http://www.slf4j.org/download.html

最后将相应的jar包都添加入eclipse工程的external jars, 就完成了我们的配置工作。

二、.thrift 文件篇:

该文件用于定义所需的数据结构及服务接口。(常用介绍,更详细的范例可以参考https://git-wip-us.apache.org/repos/asf/thrift/?p=thrift.git;a=blob;f=tutorial/tutorial.thrift;h=3150151deceb87e22123c9a321d9cd000dcfce5b;hb=HEAD )

1. 基本数据结构:

bool        Boolean, one byte
byte        Signed byte
i16         Signed 16-bit integer
i32         Signed 32-bit integer
i64         Signed 64-bit integer
double      64-bit floating point value
string      String
binary      Blob (byte array)
map<t1,t2>  Map from one type to another
list<t1>    Ordered list of one type
set<t1>     Set of unique elements of one type
           

更改基本数据结构类型名: typedef i32 MyInteger

定义常量: const i32 INT32CONSTANT = 9853

定义结构体:

struct Work {
1: i32 num1 = 0,
2: i32 num2,
3: Operation op,
4: optional string comment,// optional选项表示如果该变量的值没有被set,它就不会出现在串行化输出中
}
           

2. 定义服务:

service Calculator extends shared.SharedService {

/**
* A method definition looks like C code. It has a return type, arguments,
* and optionally a list of exceptions that it may throw. Note that argument
* lists and exception lists are specified using the exact same syntax as
* field lists in struct or exception definitions.
*/

void ping(),
i32 add(1:i32 num1, 2:i32 num2),

i32 calculate(1:i32 logid, 2:Work w) throws (1:InvalidOperation ouch),

/**
* This method has a oneway modifier. That means the client only makes
* a request and does not listen for any response at all. Oneway methods
* must be void.
*/
oneway void zip()
}
           

我们的thrift文件:

namespace java com.baidu.thrift     // 定义输出的语言类型及所属package
service Calculator{                 // 定义服务
    i32 add(1:i32 num1,2:i32 num2)
}
           

三、服务处理函数篇 我们的服务处理函数

package com.baidu.thrift;

import com.baidu.thrift.Calculator.Iface;	// 格式为 package.服务名.Iface
import org.apache.thrift.TException;	


public class CalculatorHandler implements Iface{	
	@Override
	public int add(int num1,int num2) throws TException{	//重载我们在服务中定义的函数add
		return num1+num2;
	}
	
}
           

四、服务器篇

package com.baidu.thrift;


import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TBinaryProtocol.Factory;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TThreadPoolServer;
import org.apache.thrift.server.TThreadPoolServer.Args;
import org.apache.thrift.transport.TNonblockingServerSocket;
import org.apache.thrift.transport.TTransportException;


// import the processor of service


import com.baidu.thrift.Calculator;


public class JavaServer {


	public final static int PORT = 10005;
	
	public void startServer(){
		try {
			// 定义socket
			TNonblockingServerSocket socket = new TNonblockingServerSocket(PORT);
			// 定义服务的处理器,语句格式比较固定
			final Calculator.Processor processor = new Calculator.Processor(new CalculatorHandler());
			// 定义协议
			Factory portFactory = new TBinaryProtocol.Factory(true,true);
			// 填充参数
			Args args = new Args(socket);
			args.processor(processor);
			args.protocolFactory(portFactory);
			// 创建server
			TServer server = new TThreadPoolServer(args);
			server.serve();
		}catch(TTransportException e){
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args){
		System.out.println("Server inits ...");
		JavaServer server  = new JavaServer();
		System.out.println("Server starts ...");
		server.startServer();
		System.out.println("Completed");
	}
}
           

五、客户端篇

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

public class JavaClient {
    public void startClient() {  
        TTransport transport;  
        try {  
            System.out.println("thrift client starts ");
            transport = new TSocket("localhost", JavaServer.PORT);  
            TProtocol protocol = new TBinaryProtocol(transport);  
            Calculator.Client client = new Calculator.Client(protocol);  
            transport.open();  
            System.out.println(client.add(10, 20));  
            transport.close();  
            System.out.println("Client closes");
        } catch (TTransportException e) {  
            e.printStackTrace();  
        } catch (TException e) {  
            e.printStackTrace();  
        }  
    }  
  
    public static void main(String[] args) {  
    	System.out.println("thrift client inits ");
        JavaClient client = new JavaClient();  
        System.out.println("thrift client starts ");
        client.startClient();  
        System.out.println("thrift client ends ");
    }  
}
           

注意: 定义的协议与端口需要与server端一致。最后通过client.服务 调用我们所要使用的服务

原理: 在http://www.ibm.com/developerworks/cn/java/j-lo-apachethrift/ 上有较好的说明,不赘述。

继续阅读