在阅读的过程中有不论什么问题。欢迎一起交流
邮箱:1494713801@qq.com
QQ:1494713801
一、作用
Thrift("Scalable Cross-Language Services Implementation”)最早是Facebook的项目,后来Facebook提供给Apache作为开源项目。
普通情况下的跨机器的通信框架都是跨软件平台的(Linux,windows), 而Thrift最特别之处在于它是跨语言的:比如,你能够用差点儿全部流行语言(C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript等等)来实现通讯过程,这样做的优点就是你不用为编程语言发愁。假设server端与client都须要编写,选择你最拿手或项目规定的语言,就能够生成一个通讯框架;假设编写一个server端程序,定义好通讯规则(在Thrift中是.thrift文件)后,你所採用的server端实现语言不会影响到client,以后使用的人能够採用其它编程语言来实现client。
二、Thrift组成
Thrift事实上应分成三个部分,一个叫做Thrift代码生成器。一个叫做Thrift应用框架(库),最后一个是它生成的代码。Thrift应用的基本流程例如以下图所看到的。
从上图,要生成一个Thrift应用,需用下面文件:
- 一个.thrift文件:该文件是通信接口的定义。最基本的是信息流的格式。
- 编程语言:这个无需解释。
- Thrift代码生成器(Thrift compiler,翻译成代码生成器似乎更合适):这个东西是安装thrift过程中生成的,它能够产生若干符合你约定通信格式的代码。
- Thrift应用框架库:这个东西也是在安装过程中产生的。
- 其它第三方支撑库:对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四种server框架。TSimpleServer以单一主线程堵塞的方式进行事件处理。TThreadPoolServer以多线程堵塞的方式提供服务。TNonblockingServer以多线程非堵塞方式工作。 TNonblockingServer服务模型的使用须要事先安装libevent。libevent-dev库,libevent是异步事件处理的程序库,其包括我们经常使用的poll,select,epoll等异步处理函数。
安装步骤:
$./configure
$make
#sudo make install
configure的结果最后一部分例如以下,当中 Build TNonblockingServer .. : yes的结果对于使用异步的server模型是必须的。
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 |
3 |
service HelloWorldService { |
4 |
string sayHello(1:string username) |
文件夹结构例如以下:
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; |
3 |
import org.apache.thrift.TException; |
11 |
public class HelloWorldImpl implements HelloWorldService.Iface { |
13 |
public HelloWorldImpl() { |
17 |
public String sayHello(String username) throws TException { |
18 |
return "Hi," + username + " welcome to my blog www.micmiu.com" ; |
3.TSimpleServer服务端
简单的单线程服务模型,一般用于測试。
编写服务端server代码:HelloServerDemo.java
1 |
package com.micmiu.thrift.demo; |
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; |
18 |
public class HelloServerDemo { |
19 |
public static final int
SERVER_PORT = 8090 ; |
21 |
public void startServer() { |
23 |
System.out.println( "HelloWorld TSimpleServer start ...." ); |
25 |
TProcessor tprocessor = new HelloWorldService.Processor<HelloWorldService.Iface>( |
27 |
// HelloWorldService.Processor<HelloWorldService.Iface> tprocessor = |
28 |
// new HelloWorldService.Processor<HelloWorldService.Iface>( |
29 |
// new HelloWorldImpl()); |
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); |
41 |
}
catch (Exception e) { |
42 |
System.out.println( "Server start error!!!" ); |
50 |
public static void main(String[] args) { |
51 |
HelloServerDemo server = new HelloServerDemo(); |
编写clientClient代码:HelloClientDemo.java
1 |
package com.micmiu.thrift.demo; |
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; |
18 |
public class HelloClientDemo { |
20 |
public static final String SERVER_IP =
"localhost" ; |
21 |
public static final int
SERVER_PORT = 8090 ; |
22 |
public static final int
TIMEOUT = 30000 ; |
28 |
public void startClient(String userName) { |
29 |
TTransport transport = null ; |
31 |
transport = new TSocket(SERVER_IP, SERVER_PORT, TIMEOUT); |
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( |
39 |
String result = client.sayHello(userName); |
40 |
System.out.println( "Thrify client result =: " + result); |
41 |
}
catch (TTransportException e) { |
43 |
}
catch (TException e) { |
46 |
if ( null != transport) { |
55 |
public static void main(String[] args) { |
56 |
HelloClientDemo client = new HelloClientDemo(); |
57 |
client.startClient( "Michael" ); |
先执行服务端程序。日志例如以下:
HelloWorld TSimpleServer start ....
再执行client调用程序。日志例如以下:
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/