`
autumnrain_zgq
  • 浏览: 61182 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

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的代码,增加对对象池支持。
分享到:
评论
11 楼 H_kx 2016-07-02  
fxc13120 写道
我没搞明白楼主的processor单例和对象池使用快在哪里了??
TServer server = new TThreadPoolServer(new Args(serverTransport).processor(processor));

processor在server启动前就已经初始化成单例了,在以后的服务过程中从来就没有反复创建,何须使用对象池???



同问!
博主是误人子弟了。一开始还以为是接口参数和返回值的业务对象池呢,万万没想到啊
10 楼 361010911 2016-01-07  
  不错 不错;最近遇到一个问题xlst转XML报文的时候内存不释放,不知道是不是跟单例有关。。最近在验证。
9 楼 fxc13120 2015-01-04  
我没搞明白楼主的processor单例和对象池使用快在哪里了??
TServer server = new TThreadPoolServer(new Args(serverTransport).processor(processor));

processor在server启动前就已经初始化成单例了,在以后的服务过程中从来就没有反复创建,何须使用对象池???
8 楼 HelloJimmy 2014-11-18  
如果不是特别大的吞吐量,考虑开发效率,可以考虑json来传输数据

josico 写道
问一个问题
服务端从数据库查数据,查到的数据封装成对象,并转成thrift对象传递给客户端
但如果查不到记录怎么办?
正常情况是返回null 但thrift只支持一些基本数据类型,thrift是不能传递null对象的
那就只能给他new一个thrift对象给他传过去,这个对象只是new出来的,没有任何属性
但这里又会有一个问题
thrift的一些基本数据类型是有初始值的 比如数据库中的gender性别number类型,0表示男,1表示女,在thrift对象对应中,就是对应的i64或者i32,如果数据库中gender为null,到thrift里面,应该就是这个i64或者i32为null,但基本数据类型是没法为null的,就类似int有一个初始值一样,那客户端得到的就是0,那他又不知道,到底这个gender本身在数据库存的就是0,还是说存的是NULL?
不过上述问题还可以用thrift的默认值来解决,不过总觉得很累赘
如果说,再给他包一层,把需要的thrift对象包到另一个common的thrift对象中去,这样在common的thrift中加个message,code啊什么之类的,来让客户端字段一些信息,也是可惜的
但坑爹的是,thrift居然TM不支持继承,并且官方还说以后也不会支持。。。
这TM还怎么愉快的玩耍



7 楼 liyonghui160com 2014-07-08  
楼主:单列的模式不就是创建一次吗?用对象池技术就快了吗?
6 楼 liyonghui160com 2014-07-08  
xbgd 写道
selectorThreads(60).workerThreads(20).

这个两个参数的配置是什么意思呢?



//selector线程数 selector线程负责1.事件注册 2.读写IO轮询 3.将数据读取或者写入到transport
        public int selectorThreads = 2;

        //工作线程数  负责协议的解析 对象序列化 业务逻辑的执行 响应写入到ByteBuffer 工作线程为0 就直接在selector线程上执行
        private int workerThreads = 5;
5 楼 liyonghui160com 2014-07-08  
请问,selectorThreads(60).workerThreads(20). 这两个设置多少比例最合适?
4 楼 josico 2014-05-28  
问一个问题
服务端从数据库查数据,查到的数据封装成对象,并转成thrift对象传递给客户端
但如果查不到记录怎么办?
正常情况是返回null 但thrift只支持一些基本数据类型,thrift是不能传递null对象的
那就只能给他new一个thrift对象给他传过去,这个对象只是new出来的,没有任何属性
但这里又会有一个问题
thrift的一些基本数据类型是有初始值的 比如数据库中的gender性别number类型,0表示男,1表示女,在thrift对象对应中,就是对应的i64或者i32,如果数据库中gender为null,到thrift里面,应该就是这个i64或者i32为null,但基本数据类型是没法为null的,就类似int有一个初始值一样,那客户端得到的就是0,那他又不知道,到底这个gender本身在数据库存的就是0,还是说存的是NULL?
不过上述问题还可以用thrift的默认值来解决,不过总觉得很累赘
如果说,再给他包一层,把需要的thrift对象包到另一个common的thrift对象中去,这样在common的thrift中加个message,code啊什么之类的,来让客户端字段一些信息,也是可惜的
但坑爹的是,thrift居然TM不支持继承,并且官方还说以后也不会支持。。。
这TM还怎么愉快的玩耍
3 楼 xbgd 2013-05-23  
selectorThreads(60).workerThreads(20).

这个两个参数的配置是什么意思呢?
2 楼 autumnrain_zgq 2013-05-03  
nmlnj 写道
有示例可以看看吗,我对这个东西的配置更感兴趣。

		Runnable userServer = new Runnable() {
			public void run() {
				try {
					log.info(LogUtil.formatLog("启动UserServer,端口号:[#0]...", userPort));
					// TServerTransport serverTransport = new
					// TServerSocket(userPort);
					// TServer server = new TThreadPoolServer(new
					// Args(serverTransport).minWorkerThreads(1000).maxWorkerThreads(1500).processorFactory(new
					// UserProcessorFactory(applicationContext)));
					// server.serve();

					TNonblockingServerTransport serverTransport = new TNonblockingServerSocket(userPort);
					TTransportFactory transportFactory = new TFramedTransport.Factory();
					TProtocolFactory proFactory = new TCompactProtocol.Factory();
					TServer server = new TThreadedSelectorServer(new org.apache.thrift.server.TThreadedSelectorServer.Args(serverTransport).protocolFactory(proFactory).selectorThreads(60).workerThreads(20).transportFactory(transportFactory)
							.processorFactory(new UserProcessorFactory(applicationContext, 20)));
					server.serve();
				} catch (TTransportException e) {
					log.error("启动UserServer出错,错误信息为:" + e.getMessage(), e);
				}
			}
		};
1 楼 nmlnj 2013-05-02  
有示例可以看看吗,我对这个东西的配置更感兴趣。

相关推荐

    C++(Qt)下的thrift的使用示例

    总的来说,“C++(Qt)下的thrift的使用示例”涵盖了在Qt环境下集成Thrift服务的基本步骤,包括安装依赖、编写IDL、生成代码、实现服务和客户端,以及利用Qt的特性来优化通信过程。理解并掌握这些知识,将有助于你在...

    thrift的使用介绍

    一旦有了IDL文件,你可以使用Thrift编译器生成对应语言的客户端和服务器端代码。例如,对于PHP和Python,这将生成服务接口类、协议处理类以及数据结构的序列化和反序列化代码。 - `PhpClient.php`: 这是生成的PHP...

    Thrift框架使用分享

    Thrift实现了C/S模式,使用代码生成工具根据接口定义文件生成服务器端和客户端代码,这样可以在不同的语言之间实现无缝的服务调用。用户在Thrift描述文件中声明服务后,这些服务会被编译成相应语言的代码文件,之后...

    使用wireshark抓取thrift协议接口调用

    6. **调试与优化** - 错误检测:若在Thrift接口调用中遇到问题,Wireshark可以提供网络层面的线索,比如超时、重传或错误编码。 - 性能分析:通过观察数据包的大小、间隔时间,可以评估服务的性能和响应时间,为...

    java代码使用thrift2操作hbase示例

    Thrift2是Thrift的升级版本,提供了更优化的性能和更完善的API。在Java中,我们可以利用Thrift2生成的客户端库来与HBase进行交互。以下是使用Java和Thrift2操作HBase的一些关键知识点: 1. **设置环境**:首先确保...

    spring与thrift集成

    将 Spring 与 Thrift 集成,可以利用 Spring 的强大功能来管理和调度 Thrift 服务,同时借助 Thrift 实现高效的数据传输和跨语言服务调用。 集成 Spring 和 Thrift 主要涉及以下几个步骤: 1. **创建 Thrift IDL ...

    netty+thrift高并发高性能

    本文将深入探讨Netty与Thrift结合实现高并发高性能的关键技术点。 #### 二、Netty 高性能分析 ##### 2.1 RPC调用性能瓶颈分析 在传统的RPC框架中,主要存在以下三大性能瓶颈: 1. **网络传输方式**:传统的RPC...

    thrift-0.13.0.zip

    HBase利用Thrift作为其对外的RPC接口,允许不同语言的客户端与HBase服务器进行通信。 "thrift-0.13.0.zip"这个压缩包包含了Thrift 0.13.0版本的源码和工具,用于生成Go语言的Thrift接口。Thrift IDL文件描述了HBase...

    thrift_sasl-0.3.0.tar.gz

    7. **部署与集成**:了解如何在实际环境中部署Thrift SASL,包括设置SASL配置文件、配置Thrift服务以使用SASL以及客户端的适配,是使用此库的关键步骤。 8. **测试与调试**:在生产环境中使用Thrift SASL时,进行...

    thrift开源项目研究

    这有助于优化自定义的Thrift服务,提高性能或解决特定问题。 总结,Thrift作为一款强大的跨语言通信框架,不仅简化了分布式系统的开发,还提高了系统的性能和可扩展性。通过学习和理解Thrift,开发者能够更好地应对...

    thrift1 查询hbase

    7. **优化与注意事项**:在实际应用中,需要考虑性能优化,如批量操作、合理的数据模型设计、使用过滤器减少网络传输等。同时,确保HBase和Thrift服务器的安全配置,防止未经授权的访问。 综上所述,"thrift1 查询...

    thrift-0.9.1.exe和thrift-0.9.2.exe

    0.9.1和0.9.2分别代表了Thrift的两个发行版本,每个版本可能包含了新功能、性能优化或错误修复。升级版本通常意味着更好的稳定性和兼容性,但也可能引入新的API或改变了旧有的行为。 在使用Thrift时,首先需要编写...

    基于Thrift的Golang与c#程序互相访问

    本主题将详细探讨如何使用Thrift实现Golang与C#程序之间的互相访问。 首先,让我们了解Thrift的基本概念。Thrift是一种“远程过程调用”(RPC)框架,它提供了一种轻量级的编译器,可以将接口定义语言(IDL)转换为...

    thrift阻塞与非阻塞模式下的测试

    通过对Thrift阻塞和非阻塞模式的测试,我们可以得出适合特定业务场景的最佳实践,优化服务性能,提高系统的整体效率。在实际应用中,可能需要结合具体情况,选择单线程阻塞、多线程阻塞、异步IO、NIO或AIO等模式的...

    Laravel开发-thrift-laravel

    【Laravel开发与Thrift-Laravel整合】 ...Thrift则是一个跨语言的服务框架,由Facebook开源,用于实现高性能、可扩展的服务...通过理解和掌握Thrift-Laravel,开发者可以提升服务之间的通信效率,优化整体系统的架构。

    thrift-0.11.0

    7. 集成工具:Thrift可以与构建工具(如maven、gradle)无缝集成,简化项目的构建和部署过程。 在Thrift-0.11.0中,可能会有以下改进: - 性能优化:可能通过改进内部算法或数据结构,提高了编译速度和运行时效率...

    Thrift--JSClient

    5. **跨平台通信**:可能涉及如何在Web应用中使用Thrift JSClient与后端服务(可能是Java、Python或其他语言)进行通信。 6. **示例代码**:通常会提供实际的JavaScript代码片段,展示如何创建Thrift客户端对象,...

    thrift操作Hbase数据库

    在C#环境中,我们需要安装Thrift的C#绑定库,并使用Thrift编译器将Hbase的Thrift IDL文件转换为C#代码。这些生成的代码包含了Hbase服务的客户端类,用于创建连接、执行操作等。 3. **连接Hbase** 使用Thrift生成...

    thrift 教程

    9. **性能优化**:Thrift 本身已经做了很多性能优化,但在实际应用中,可能还需要根据业务需求进行定制化优化,如选择合适的传输层和协议,调整连接池大小等。 10. **最佳实践**:教程中可能会涵盖如何设计高效的...

    thrift包及其源码

    12. **性能优化**:Thrift的高性能得益于其轻量级的通信模型和高效的序列化机制,但在实际应用中,还需要根据场景调整服务器配置,优化网络通信,以获得最佳性能。 总结,这个“thrift包及其源码”为学习和使用...

Global site tag (gtag.js) - Google Analytics