thrift 轻松实现多语言跨服务器通信

Posted by admin on 2013, July 30

thrift是由facebook开发的轻量级跨语言的服务框架,现在已经移交到apache基金会下。和他类似的是google出的protocol buffer和ice。 thrift的一大优势就是支持的语言很丰富,它使用自己的IDL语言来描述服务接口和数据交换的格式。

官方网站:http://incubator.apache.org/thrift/

一、安装:

yum -y install gcc-c++ autoconf automake sysconftool boost /
    boost-devel libtool perl-ExtUtils-MakeMaker gettext-base /
    gettext gettext-devel liblocale-gettext-perl zlib-devel /
    byacc bison flex pkgconfig python-devel 

wget http://apache.freelamp.com/incubator/thrift/0.2.0-incubating/thrift-0.2.0-incubating.tar.gz

./bootstrap.sh 
./configure --prefix=/usr/local/thrift --with-ruby=no --with-erlang=no --with-java=no --with-csharp=no --enable-gen-java=no --enable-gen-csharp=no --enable-gen-rb=no --enable-gen-erl=no
make
make install

二、IDL描述:

1.支持的变量类型

  
类型          描述    
bool            #true, false    
byte            #8位的有符号整数    
i16             #16位的有符号整数    
i32             #32位的有符号整数    
i64             #64位的有符号整数    
double          #64位的浮点数    
string          #UTF-8编码的字符串    
binary          #字符数组    
struct          #结构体    
list<type>        #有序的元素列表,类似于STL的vector    
set<type>     #无序的不重复元素集,类似于STL的set    
map<type1,type2>  #key-value型的映射,类似于STL的map    
exception       #是一个继承于本地语言的exception基类    
service         #服务包含多个函数接口(纯虚函数)    

 

  1. 摘一段例子上来,让瞧瞧这是啥东东。(本例子文件名为:tutorial.thrift,是本身带的教程。)   
include "shared.thrift"
   
   
namespace cpp tutorial  
namespace java tutorial  
namespace php tutorial  
namespace perl tutorial  
namespace smalltalk.category Thrift.Tutorial  
   
typedef i32 MyInteger  
   
const i32 INT32CONSTANT = 9853  
const map<string,string> MAPCONSTANT = {'hello':'world', 'goodnight':'moon'}  
   
enum Operation {  
  ADD = 1,  
  SUBTRACT = 2,  
  MULTIPLY = 3,  
  DIVIDE = 4  
}  
   
struct Work {  
  1: i32 num1 = 0,  
  2: i32 num2,  
  3: Operation op,  
  4: optional string comment,  
}  
   
exception InvalidOperation {  
  1: i32 what,  
  2: string why  
}  
   
service Calculator extends shared.SharedService {  
   
   void ping(),  
   
   i32 add(1:i32 num1, 2:i32 num2),  
   
   i32 calculate(1:i32 logid, 2:Work w) throws (1:InvalidOperation ouch),  
   
   oneway void zip()  
   
} 

3. 我们来写个 helloworld.thrift  

service HelloWorld{  
 string ping(1: string name),  
 string getpng(),  
}

三、编译 helloworld:

  1. /usr/local/thrift/bin/thrift -r –gen py helloworld.thrift  

  2. /usr/local/thrift/bin/thrift -r –gen php helloworld.thrift  

  3. #会在当前目录下生成 gen-* 目录。  

四、编写服务器端:



[python] view plaincopyprint?

import sys  
sys.path.append('./gen-py')  
   
from helloworld import HelloWorld  
from helloworld.ttypes import *  
   
from thrift.transport import TSocket  
from thrift.transport import TTransport  
from thrift.protocol import TBinaryProtocol  
 from thrift.server import TServer  
    
 class HellowordHandler:  
     def __init__ (self):  
         pass  
    
     def ping (self, name):  
         print name + ' from server.'  
         return "%s from server." % name  
     def getpng (self):  
         f = open("./logo.png", "rb")  
         c = f.read()  
         f.close()  
         return c  
 handler = HellowordHandler()  
 processor = HelloWorld.Processor(handler)  
 transport = TSocket.TServerSocket(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.'  


五、编写客户端:

[php] view plaincopyprint?

<?php  
try{  
   
    $GLOBALS['THRIFT_ROOT'] = './php/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';  
     error_reporting(E_NONE);  
     $GEN_DIR = './gen-php';  
     require_once $GEN_DIR.'/helloworld/HelloWorld.php';  
     error_reporting(E_ALL);  
    
     $socket = new TSocket('*.*.*.*', 9090);  
     $transport = new TBufferedTransport($socket, 1024, 1024);  
     $protocol = new TBinaryProtocol($transport);  
     $client = new HelloWorldClient($protocol);  
    
     $transport->open();  
    
     $a = $client->ping('xyq ');  
     echo $a;  
    
     $transport->close();  
    
     } catch (TException $tx) {  
         print 'TException: '.$tx->getMessage()."/n";  
     }  
    
 ?>  

按上面的流程就可以写自己的thrift了,我使用py做服务端,用php做客户端,当然也可以使用c++来做服务端。

相关文章:

thrift 安装 http://wiki.apache.org/thrift/ThriftInstallation redis + thrift + mongodb 数据测试 http://www.ys250.com/2010/09/02/redis-thrift-mongodb-test/ Thrift基本使用 http://hi.baidu.com/infant/blog/item/01fa53436adc79189313c69e.html