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

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 test

struct 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 {

	@Override
	public int testCase1(int num1, int num2, String num3) throws TException {
		// TODO Auto-generated method stub
		return 1;
	}

	@Override
	public List<String> testCase2(Map<String, String> num1) throws TException {
		List<String> list = new ArrayList<String>();
		list.add("aaa");
		list.add("bbb");
		return list;
	}

	@Override
	public void testCase3() throws TException {
		System.out.println("testCase3");		
	}

	@Override
	public 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,编码如下:

<?php
use Thrift\Transport\TSocket as TSocket;
use Thrift\Transport\TBufferedTransport as TBufferedTransport;
use Thrift\Protocol\TBinaryProtocol as TBinaryProtocol;

use test\ThriftCaseClient as ThriftCaseClient;

// autoload function
function __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中随便写的):

1
array(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的配置信息。


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值