Thrift的使用与优化

去年一年的时间中,用Thrift提供服务的方式,开发了一个用户中心系统,以便于与其它的各个业务系统进行相应的集成。
在生产环境中,ThriftServer的选择是很重要的。建议在TThreadPoolServer和 TThreadedSelectorServer中进行相应的选择。个人建议选择TThreadedSelectorServer,因为其支持网络NIO,在一个业务的处理过程中,很大一部分时间会阻塞在网络通信上,并且TThreadedSelectorServer能吞吐更多的网络连接,而ThreadPoolServer吞吐的网络连接数和其启动的线程数量有关,如果存在客户端调用代码未正常关闭Transport时,其网络连接只有在时间超时时才会正常释放掉,造成服务的无法正常提供。
具体的参考资料见:http://www.codelast.com/?p=4824
本人在实际应用的过程中,是使用Spring+Mybatis+Thrift方式。在Spring中,重量级的业务处理Service的创建是非常耗时的,所以对于这些Service,一定要用对象池将期存储起来,防止Thrift在处理业务的过程中,频繁的创建业务对象,消耗系统资源。
默认的情况下,TProcessorFactory是使用了单列的模式,所以要对TProcessorFactory进行扩展,并使其支持对象池技术,增加释放处理对象的方法returnProcessor,如以下代码:
package org.apache.thrift;

import org.apache.thrift.transport.TTransport;

/**
* The default processor factory just returns a singleton instance.
*/
public class TProcessorFactory {

private final TProcessor processor_;

public TProcessorFactory(TProcessor processor) {
processor_ = processor;
}

public TProcessor getProcessor(TTransport trans) {
return processor_;
}

public void returnProcessor(TProcessor _tprocessor) {

}

}


将使用完的对象释放到连接池中,并更改调用getProcessor方法的地方,释放相应的Processor.将业务实现代码中,从对象池中获取处理对象

在业务系统代码中的实现如下:

package com.hoodinn.user.service.thrift;

import org.apache.commons.pool.impl.StackObjectPool;
import org.apache.log4j.Logger;
import org.apache.thrift.TProcessor;
import org.apache.thrift.TProcessorFactory;
import org.apache.thrift.transport.TTransport;
import org.springframework.context.ApplicationContext;

import com.hoodinn.user.connector.thrift.UserAcceptor;

/**
* @author MatrixZhang
* @createTime 2012-8-16 下午7:42:27
* @Description
*/
public class UserProcessorFactory extends TProcessorFactory {

private StackObjectPool<TProcessor> sop;

static Logger log = Logger.getLogger(UserProcessorFactory.class);

public UserProcessorFactory(ApplicationContext applicationContext, Integer poolSize) {
super(null);
sop = new StackObjectPool<TProcessor>(new USPoolFactory(applicationContext) {
@Override
public TProcessor selfMakeObject() {
return new UserAcceptor.Processor<UserAcceptorService>(applicationContext.getBean(UserAcceptorService.class));
}
}, poolSize + 2);
}

@Override
public TProcessor getProcessor(TTransport trans) {
try {
return sop.borrowObject();
} catch (Exception e) {
log.error("获取UserAcceptorService时出错!", e);
return null;
}
}

@Override
public void returnProcessor(TProcessor _tprocessor) {
try {
sop.returnObject(_tprocessor);
} catch (Exception e) {
log.error("归还UserAcceptorService时出错", e);
}
}

}

这样使用对象池技术以后,Thrift接口的数据吞吐量能有一个大幅度的提升。另外,在使用Thrift设计相应的接口时,建议使用字符串对JSON的格式进行相应的数据传输。在接口设计时,只设计上两个接口,一个是前端业务处理,一个是后台业务处理 。如以下的定义方式:
service ThirdSnsAcceptor{

/** 接口服务的处理 */
string businessProcess(1:string param);

/** 后台管理业务的处理 */
string adminProcess(1:string param);

}

在实际的使用过程中,我发现使用纯正的接口对象传输和使用JSON的性能差异不大。因为Jackson的解析性能还是非常可观的,这样,接口定义以后,基本上不需要有任何改动了。对于接口数据的定义,可以使用以下的方式:
{
"name":"addFriend",
"version":"1.0",
"param":{
"appId":1,
"userId":1,
"platform":"WEIBO"
}
}

这样,可以以name和version实现不同的业务处理分支跳转。


这是本人的一点经验总结,如有什么不足之处,欢迎大爱回复,讨论。
附件是我更改过的Thrift的代码,增加对对象池支持。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值