多语言协作工具thrift实例讲解

来源:互联网 发布:vb安装包下载 编辑:程序博客网 时间:2024/04/26 12:44

1背景

如果讨论每个语言的特点,相信各个语言的程序员都能说得天花乱坠,争的面红耳赤。但是在如今大互联网时代,没有哪种语言是银弹,各种语言都各有所长。为了截取各家之长,各种跨语言通信框架涌现出来,thrift就是其中的一个典型代表。

thrift是基于socket或者http协议来进行通信的,所以适合分布式的服务器之间进行通信。众所周知,php中是无法使内存常驻的,java、c、c++之类的就可以;对于处理html页面,php擅长,对于数据库连接java更擅长,对于高并发处理node.js erlang更擅长。thrift将各者结合起来,做到扬长避短,而且支持的语言要远远多于刚才提到几种。

关于thrift的入门介绍可以参见http://www.javabloger.com/article/apache-thrift-architecture.html

2安装

下面以java和php为例介绍一下thrift的使用。

首先从https://dist.apache.org/repos/dist/release/thrift/0.9.0/thrift-0.9.0.tar.gz 下载最新的thrift源码和在windows下的工具https://dist.apache.org/repos/dist/release/thrift/0.9.0/thrift-0.9.0.exe。将thrift-0.9.0.tar.gz解压到任意目录,在里面新建目录bin,将thrift-0.9.0.exe拷贝到这个目录,重命名为thrift.exe,并且将这个bin目录加入环境变量,方便以后从命令行。

进入thrift解压目录下的lib/java目录,执行ant命令(关于ant的配置,请自行搜索,当然也可以下载随后给出的ant生成物),在生成的build目录中的libthrift-0.9.0.jar和build/lib目录中的所有jar包备份出来,方便建立java项目时引用。

注意php需要配置apc支持,如果没有安装会影响其性能,固请先安装之(配置步骤可参阅附录)。

3脚本编写

新建thrift数据定义文件test.txt内容如下:

namespace java com.whyun.thrift   # 注释1   定义生成代码的命名空间,与你需要定义的package相对应。namespace php teststruct Blog {   #  注释2.1   定义实体名称和数据结构,类似你业务逻辑中的pojo get/set    1: string topic     #  注释2.2  参数类型可以参见 Thrift wiki       2: binary content      3: i64    createdTime    4: string id    5: string ipAddress    6: map<string,string> props  }service ThriftCase {  #  注释3    代码生成的类名,你的业务逻辑代码需要实现代码生成的ThriftCase.Iface接口    i32 testCase1(1:i32 num1, 2:i32 num2, 3:string  num3) #注释4.1 方法名称和方法中的入参,入参类型参见wiki    list<string> testCase2(1:map<string,string>  num1)    void testCase3()    void testCase4(1:list<Blog> blog)   #  注释4.2   list 是thrift中基本数据类型中的一种,list中包含的Blog对象是上面struct中定义的}

在test.txt所在目录下运行thrift --gen java test.txt生成java代码,运行thrift --gen php test.txt来生成php代码,运行完成后,在当前目录下回生成gen-java和gen-php两个目录。

4java代码编写

新建java项目thrift-demo,在项目中新建目录lib,将刚才安装中生成的jar包都拷贝过来,并将其添加到classpath中,将之前生成的gen-java目录下生成代码拷贝到工程中,然后新建包com.whyun.thrift.business来编写我们的处理代码,首先实现sevice的处理类,如下:

package com.whyun.thrift.business;import java.util.ArrayList;import java.util.List;import java.util.Map;import org.apache.thrift.TException;import com.whyun.thrift.Blog;import com.whyun.thrift.ThriftCase.Iface;public class CaseImpl implements Iface {@Overridepublic int testCase1(int num1, int num2, String num3) throws TException {// TODO Auto-generated method stubreturn 1;}@Overridepublic List<String> testCase2(Map<String, String> num1) throws TException {List<String> list = new ArrayList<String>();list.add("aaa");list.add("bbb");return list;}@Overridepublic void testCase3() throws TException {System.out.println("testCase3");}@Overridepublic void testCase4(List<Blog> blog) throws TException {System.out.println("testCase4");}}

代码片段4.1

接着编写server端程序:

package com.whyun.thrift.business;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.TServerSocket;import org.apache.thrift.transport.TTransportException;import com.whyun.thrift.ThriftCase;import com.whyun.thrift.ThriftCase.Processor;public class Server {   public void startServer() {       try {           TServerSocket serverTransport = new TServerSocket(1234);           ThriftCase.Processor process = new Processor(new CaseImpl());           Factory portFactory = new TBinaryProtocol.Factory(true, true);           Args args = new Args(serverTransport);           args.processor(process);           args.protocolFactory(portFactory);           TServer server = new TThreadPoolServer(args);           server.serve();       } catch (TTransportException e) {           e.printStackTrace();       }   }   public static void main(String[] args) {       Server server = new Server();       server.startServer();   }}

代码片段4.2

5php程序编写

在apache的web根目录中新建文件夹thrift,在其下新建classes目录。在将安装步骤中thrift解压目录下的lib/php/lib目录下Thrift文件夹拷贝到新建的classes目录下,再将脚本编写步骤中gen-php目录下test文件夹拷贝到classes目录中,将test文件夹下的ThriftCase.php改名为ThriftCaseClient.php,最终形成的目录结构如下:


图5.1

在thrift目录下新建package.php,编码如下:

<?phpuse Thrift\Transport\TSocket as TSocket;use Thrift\Transport\TBufferedTransport as TBufferedTransport;use Thrift\Protocol\TBinaryProtocol as TBinaryProtocol;use test\ThriftCaseClient as ThriftCaseClient;// autoload functionfunction __autoload($class) {// convert namespace to full file path$class = 'classes/'.str_replace('\\', '/', $class). '.php';require_once($class);}$thriftHost = '127.0.0.1'; //Thrift接口服务器IP$thriftPort = 1234;//Thrift接口服务器端口$socket = new TSocket($thriftHost, $thriftPort);$socket->setSendTimeout(10000);$socket->setRecvTimeout(20000);$transport = new TBufferedTransport($socket);$protocol = new TBinaryProtocol($transport);$client = new ThriftCaseClient($protocol);$transport->open();$socket->setDebug(TRUE);echo $client->testCase1(1,2,3).'<br />';var_dump( $client->testCase2(array('xxx'=>'1','ddd'=>'2')));?>

代码片段5.1

6运行

在eclipse中运行代码片段4.2,然后在浏览器中运行代码片段5.1,会输出(这些输出其实是由于在代码片段4.1中随便写的):

1array(2) { [0]=> string(3) "aaa" [1]=> string(3) "bbb" }

以上java和php代码已上传到csdn http://download.csdn.net/detail/yunnysunny/5097464。

附录 APC配置

由于php在使用thrift的时候需要配置APC,这里简单说明一下。首先运行phpinfo()函数,如果没有APC的配置信息,则说明之前没有安装,然后查找Zend Extension Build内容,如果显示为类似API220090626,TS,VC9 字样,则表明当前php为线程安全版本,如果当中的TS换成了NTS,则表明为非线程安全版本。然后去http://downloads.php.net/pierre/ 下载相应的版本,如果是线程安全版本,则可以下载apc-igbinary-fastlz-snap20110301-5.3-ts-vc9-x86.zip。

解开zip文件,将里面的dll放到php目录下的ext目录下。
修改php.ini,添加如下配置
[apc]
extension="php_apc.dll"
apc.enabled=1
apc.shm_segments=1
apc.shm_size=48M
apc.ttl=7200
apc.user_ttl=7200
apc.num_files_hint=1024
apc.mmap_file_mask=d:/tmp/apc.map
apc.enable_cli=1

其中的配置选项,则可以参阅http://www.php.net/manual/zh/apc.configuration.php。注意新版本的apc要求apc的内存占用大小的配置项目后面带上M或者G,代表MB或者GB,否则apache在启动的时候会崩溃,php的错误日志会提示apc.shm_size now uses M/G suffixes 。

安装完成后,在运行一遍phpinfo,会发现APC的配置信息。


原创粉丝点击