Apache的开源项目thrift概述

一、作用

     Thrift("Scalable Cross-Language Services Implementation”)最早是Facebook的项目,后来Facebook提供给Apache作为开源项目。

     一般情况下的跨机器的通信框架都是跨软件平台的(Linux,windows), 而Thrift最特别之处在于它是跨语言的:例如,你可以用几乎所有流行语言(C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript等等)来实现通讯过程,这样做的好处就是你不用为编程语言发愁,如果服务器端与客户端都需要编写,选择你最拿手或项目规定的语言,就可以生成一个通讯框架;如果编写一个服务器端程序,定义好通讯规则(在Thrift中是.thrift文件)后,你所采用的服务器端实现语言不会影响到客户端,以后使用的人可以采用其他编程语言来实现客户端。

二、Thrift组成

     Thrift其实应分成三个部分,一个叫做Thrift代码生成器,一个叫做Thrift应用框架(库),最后一个是它生成的代码。Thrift应用的基本流程如下图所示。

从上图,要生成一个Thrift应用,需用以下文件:

  1. 一个.thrift文件:该文件是通信接口的定义,最主要的是信息流的格式。
  2. 编程语言:这个无需解释。
  3. Thrift代码生成器(Thrift compiler,翻译成代码生成器似乎更合适):这个东西是安装thrift过程中生成的,它可以产生若干符合你约定通信格式的代码。
  4. Thrift应用框架库:这个东西也是在安装过程中产生的。
  5. 其他第三方支撑库:对C++来说,最主要是boost.thread、libevent,log4cxx等,按照运行的模式,生成的代码中可能需用调用这些库。

三、Thrift的安装及使用

1、安装

安装版本为:Thrift v0.9.1

系统版本:Ubuntu 14.04 64位

基本安装环境:

  • g++ 4.2
  • boost 1.53.0
  • libssl-dev

Thrift的编译器即代码生成器是由C++编写的,所以需要g++来进行编译安装,且Thrift源码中用到了boost库中相关实现,例如shared_ptr,所以要事先安装boost库。

Thrift通信过程中使用ssl对数据进行安全包含,如果为安装该库,会在configure时出现 configure: error: "Error: libcrypto required."

Thrift提供了,TThreadSever, TThreadPoolServer, TNonblockingServer四种服务器框架,TSimpleServer以单一主线程阻塞的方式进行事件处理,TThreadPoolServer以多线程阻塞的方式提供服务,TNonblockingServer以多线程非阻塞方式工作。 TNonblockingServer服务模型的使用需要事先安装 libevent,libevent-dev 库,libevent是异步事件处理的程序库,其包含我们常用的poll,select,epoll等异步处理函数。

安装步骤:

$./configure
$make
#sudo make install

configure的结果最后一部分如下,其中 Build TNonblockingServer .. : yes 的结果对于使用异步的服务器模型是必须的。

anonymalias@anonymalias-Rev-1-0:~/download/thrift-0.9.1$./configure
......
thrift 0.9.1

Building C++ Library ......... : yes
Building C (GLib) Library .... : no
Building Java Library ........ : no
Building C# Library .......... : no
Building Python Library ...... : yes
Building Ruby Library ........ : no
Building Haskell Library ..... : no
Building Perl Library ........ : no
Building PHP Library ......... : no
Building Erlang Library ...... : no
Building Go Library .......... : no
Building D Library ........... : no

C++ Library:
  Build TZlibTransport ...... : yes
  Build TNonblockingServer .. : yes
  Build TQTcpServer (Qt) .... : no

Python Library:
  Using Python .............. : /usr/bin/python

If something is missing that you think should be present,
please skim the output of configure to find the missing
component.  Details are present in config.log.

在本人电脑上make的时候会出现下面的bug,
ar: .libs/ThriftTest_constants.o: No such file or directory

不知道Makefile如何生成的,导致上面这个编译文件路径有问题,解决方法有下面两种:

method1:
解决的方法时直接从Github(git://git.apache.org/thrift.git)上git clone 源码,先运行./bootstrap.sh,在按照configure安装。

method2:
可以将已经编译的test/cpp/*.o复制到test/cpp/.libs后,继续编译就可以了
cp test/cpp/*.o test/cpp/.libs/

2、使用

1. thrift生成代码

创建Thrift文件:G:\test\thrift\demoHello.thrift ,内容如下:

1 namespace java com.micmiu.thrift.demo
2  
3 service  HelloWorldService {
4   string sayHello(1:string username)
5 }

目录结构如下:

G:\test\thrift>tree /F
卷 other 的文件夹 PATH 列表
卷序列号为 D238-BE47
G:.
    demoHello.thrift
    demouser.thrift
    thrift-0.8.0.exe

没有子文件夹

thrift-0.8.0.exe 是官网提供的windows下编译工具,运用这个工具生成相关代码:

1 thrift-0.8.0.exe -r -gen java ./demoHello.thrift

生成后的目录结构如下:

G:\test\thrift>tree /F
卷 other 的文件夹 PATH 列表
卷序列号为 D238-BE47
G:.
│  demoHello.thrift
│  demouser.thrift
│  thrift-0.8.0.exe
│
└─gen-java
    └─com
        └─micmiu
            └─thrift
                └─demo
                        HelloWorldService.java

2. 实现接口Iface

java代码:HelloWorldImpl.java

1 package com.micmiu.thrift.demo;
2  
3 import org.apache.thrift.TException;
4  
5 /**
7  *
8  * @author Michael
9  *
10  */
11 public class HelloWorldImpl implements HelloWorldService.Iface {
12  
13     public HelloWorldImpl() {
14     }
15  
16     @Override
17     public String sayHello(String username) throws TException {
18         return "Hi," + username + " welcome to my blog www.micmiu.com";
19     }
20  
21 }

3.TSimpleServer服务端

简单的单线程服务模型,一般用于测试。

编写服务端server代码:HelloServerDemo.java

1 package com.micmiu.thrift.demo;
2  
3 import org.apache.thrift.TProcessor;
4 import org.apache.thrift.protocol.TBinaryProtocol;
5 import org.apache.thrift.protocol.TCompactProtocol;
6 import org.apache.thrift.protocol.TJSONProtocol;
7 import org.apache.thrift.protocol.TSimpleJSONProtocol;
8 import org.apache.thrift.server.TServer;
9 import org.apache.thrift.server.TSimpleServer;
10 import org.apache.thrift.transport.TServerSocket;
11  
12 /**
13  * blog http://www.micmiu.com
14  *
15  * @author Michael
16  *
17  */
18 public class HelloServerDemo {
19     public static final int SERVER_PORT = 8090;
20  
21     public void startServer() {
22         try {
23             System.out.println("HelloWorld TSimpleServer start ....");
24  
25             TProcessor tprocessor = new HelloWorldService.Processor<HelloWorldService.Iface>(
26                     new HelloWorldImpl());
27             // HelloWorldService.Processor<HelloWorldService.Iface> tprocessor =
28             // new HelloWorldService.Processor<HelloWorldService.Iface>(
29             // new HelloWorldImpl());
30  
31             // 简单的单线程服务模型,一般用于测试
32             TServerSocket serverTransport = new TServerSocket(SERVER_PORT);
33             TServer.Args tArgs = new TServer.Args(serverTransport);
34             tArgs.processor(tprocessor);
35             tArgs.protocolFactory(new TBinaryProtocol.Factory());
36             // tArgs.protocolFactory(new TCompactProtocol.Factory());
37             // tArgs.protocolFactory(new TJSONProtocol.Factory());
38             TServer server = new TSimpleServer(tArgs);
39             server.serve();
40  
41         } catch (Exception e) {
42             System.out.println("Server start error!!!");
43             e.printStackTrace();
44         }
45     }
46  
47     /**
48      * @param args
49      */
50     public static void main(String[] args) {
51         HelloServerDemo server = new HelloServerDemo();
52         server.startServer();
53     }
54  
55 }

编写客户端Client代码:HelloClientDemo.java

1 package com.micmiu.thrift.demo;
2  
3 import org.apache.thrift.TException;
4 import org.apache.thrift.protocol.TBinaryProtocol;
5 import org.apache.thrift.protocol.TCompactProtocol;
6 import org.apache.thrift.protocol.TJSONProtocol;
7 import org.apache.thrift.protocol.TProtocol;
8 import org.apache.thrift.transport.TSocket;
9 import org.apache.thrift.transport.TTransport;
10 import org.apache.thrift.transport.TTransportException;
11  
12 /**
13  * blog http://www.micmiu.com
14  *
15  * @author Michael
16  *
17  */
18 public class HelloClientDemo {
19  
20     public static final String SERVER_IP = "localhost";
21     public static final int SERVER_PORT = 8090;
22     public static final int TIMEOUT = 30000;
23  
24     /**
25      *
26      * @param userName
27      */
28     public void startClient(String userName) {
29         TTransport transport = null;
30         try {
31             transport = new TSocket(SERVER_IP, SERVER_PORT, TIMEOUT);
32             // 协议要和服务端一致
33             TProtocol protocol = new TBinaryProtocol(transport);
34             // TProtocol protocol = new TCompactProtocol(transport);
35             // TProtocol protocol = new TJSONProtocol(transport);
36             HelloWorldService.Client client = new HelloWorldService.Client(
37                     protocol);
38             transport.open();
39             String result = client.sayHello(userName);
40             System.out.println("Thrify client result =: " + result);
41         } catch (TTransportException e) {
42             e.printStackTrace();
43         } catch (TException e) {
44             e.printStackTrace();
45         } finally {
46             if (null != transport) {
47                 transport.close();
48             }
49         }
50     }
51  
52     /**
53      * @param args
54      */
55     public static void main(String[] args) {
56         HelloClientDemo client = new HelloClientDemo();
57         client.startClient("Michael");
58  
59     }
60  
61 }

先运行服务端程序,日志如下:

HelloWorld TSimpleServer start ....

再运行客户端调用程序,日志如下:

Thrify client result =: Hi,Michael welcome to my blog www.micmiu.com

测试成功,和预期的返回信息一致。

 

参考: http://blog.csdn.net/guxch/article/details/12157151

              http://blog.csdn.net/anonymalias/article/details/26154405

              http://www.micmiu.com/soa/rpc/thrift-sample/

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。