引用网上对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无论在性能、传输大小上有明显的优势。
主要根据这里的教程:
http://www.thrift.pl/Thrift-tutorial-our-own-hello-world.html
这里面的有几处错误,可能是老版本的thrift。
首先下载安装thrift最新版本。编译安装步骤:
sudo apt-get install libboost-dev libboost-test-dev libboost-program-options-dev libevent-dev automake libtool flex bison pkg-config g++ libssl-dev wget -c https://dist.apache.org/repos/dist/release/thrift/0.8.0/thrift-0.8.0.tar.gz tar -zvxf thrift-0.8.0.tar.gz cd thrift-0.8.0 ./configure make sudo make install
安装好后,安装相应的python库,不然在运行python实例的时候会提示“ImportError: No module named Thrift”错误。
cd thrift-0.8.0/lib/py sudo python setup.py install
ok,现在我们来生成一个thrift文件,定义一个数据类型与方法,在thrift-0.8.0文件夹下面创建hello.thrift文件:
namespace php hello
enum SexType {
MALE = 1,
FEMALE = 2
}
struct User {
1: string firstname,
2: string lastname,
3: i32 user_id,
4: SexType sex,
5: bool active = false,
6: optional string description
}
exception InvalidValueException {
1: i32 error_code,
2: string error_msg
}
service UserManager {
void ping(),
i32 add_user(1:User u) throws (1: InvalidValueException e),
User get_user(1:i32 uid) throws (1: InvalidValueException e),
oneway void clear_list()
}
首先我们定义了一个在php代码下的命名空间,namespace php hello。这样在生成相应的php代码后,php类名前加有hello_的前缀。
然后定义了一个性别的枚举类型SexType。
再下面就是结构体User,在定义字段的时候,每个字段前必须加一个序号,后面根数据类型。可以给字段设置默认值,如bool active = false。默认情况下所有字段都为必需,要使其为可选,可加optional修饰符。
exception InvalidValueException 定义了一个异常,当传递的参数不合法时,就抛出此异常。
接下来定义了一个服务类 UserManager,下面是一些方法。格式根我们编程定义的类似,很容易看懂。
最后一个方法加了oneway,表名在客户端调用此方法时,不用等待服务端返回就立马结束。
下面我们用thrift命名来生成相应的代码:
thrift -r --gen php hello.thrift thrift -r --gen py hello.thrift
这时候,在目录下面出现两个目录,gen-py和gen-php,分别为php与python的代码。
我们用python来写服务端,新建python_server.py:
#!/usr/bin/env python
import sys
sys.path.append('./gen-py')
from hello import UserManager
from hello.ttypes import *
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
from thrift.server import TServer
users = []
class UserManagerHandler:
def __init__(self):
pass
#self.log = {}
def ping(self):
print 'ping()'
def add_user(self, user):
if user.firstname == None:
raise InvalidValueException(1,'no firstname exception')
if user.lastname == None:
raise InvalidValueException(2, 'no lastname exception')
if user.user_id <= 0:
raise InvalidValueException(3, 'wrong user_id')
if user.sex != SexType.MALE and user.sex != SexType.FEMALE:
raise InvalidValueException(4, 'wrong sex id')
print 'Processing user '+user.firstname+' '+user.lastname
users.append(user)
print users
return True
def get_user(self, user_id):
if user_id < 0:
raise InvalidValueException(5, 'wrong id')
return users[user_id]
def clear_list(self):
print 'Clearing list'
print users
del users [:]
print users
handler = UserManagerHandler()
processor = UserManager.Processor(handler)
transport = TSocket.TServerSocket(port=9090)
tfactory = TTransport.TBufferedTransportFactory()
pfactory = TBinaryProtocol.TBinaryProtocolFactory()
server = TServer.TSimpleServer(processor, transport, tfactory, pfactory)
# You could do one of these for a multithreaded server
#server = TServer.TThreadedServer(processor, transport, tfactory, pfactory)
#server = TServer.TThreadPoolServer(processor, transport, tfactory, pfactory)
print 'Starting the server...'
server.serve()
print 'done.'
sys.path.append(‘./gen-py’) 这句话是把我们之前用thrift生成的python类代码引用进来。
然后我们运行此服务端:
chmod +x ./python_server.py ./python_server.py
接下来我们用php来实现客户端,当执行php页面后,php去连接python的服务端,调用相应的方法等。
在apache网站根目录下面,我们创建一个文件夹来放示例php代码。
cd ~/www/ mkdir thrift-php cd thrift-php cp -r ~/thrift-0.8.0/lib/php/src/ . #要用到thrift的php类库 cd src mkdir packages cd packages cp -r ~/thrift-0.8.0/gen-php/hello/ . #将我们之前生成的hello的php部分代码复制过来
然后我们在thrift-php目录下面新建hello.php文件:
<?php
$GLOBALS['THRIFT_ROOT'] = 'src';
require_once $GLOBALS['THRIFT_ROOT'].'/Thrift.php';
require_once $GLOBALS['THRIFT_ROOT'].'/protocol/TBinaryProtocol.php';
require_once $GLOBALS['THRIFT_ROOT'].'/transport/TSocket.php';
require_once $GLOBALS['THRIFT_ROOT'].'/transport/THttpClient.php';
require_once $GLOBALS['THRIFT_ROOT'].'/transport/TBufferedTransport.php';
require_once $GLOBALS['THRIFT_ROOT'].'/packages/hello/UserManager.php';
try {
$socket = new TSocket('localhost', 9090);
$transport = new TBufferedTransport($socket, 1024, 1024);
$protocol = new TBinaryProtocol($transport);
$client = new hello_UserManagerClient($protocol);
$transport->open();
$client->ping();
$u = new hello_User();
$u->user_id = 1;
$u->firstname = 'John';
$u->lastname = 'Smith';
$u->sex = SexType::MALE;
if ($client->add_user($u))
{
echo 'user added succesfully</br>';
}
var_dump($client->get_user(0));
$client->clear_list();
$u2 = new hello_User();
$client->add_user($u2);
} catch (hello_InvalidValueException $e) {
echo $e->error_msg.'<br/>';
}
?>
现在就可以在浏览器中运行我们的php客户端了,打开 http://127.0.0.1/thrift-php/hello.php,显示:
user added succesfully</br>object(hello_User)#7 (6) {
["firstname"]=>
string(4) "John"
["lastname"]=>
string(5) "Smith"
["user_id"]=>
int(1)
["sex"]=>
int(1)
["active"]=>
bool(false)
["description"]=>
NULL
}
no firstname exception
在python的服务器输出:
Starting the server... ping() Processing user John Smith [User(user_id=1, description=None, firstname='John', lastname='Smith', sex=1, active=False)] Clearing list [User(user_id=1, description=None, firstname='John', lastname='Smith', sex=1, active=False)] []
ok,最基本的hello例子就完成了。
在这里还能找到更加丰富的例子:
https://github.com/apache/thrift/tree/trunk/tutorial