`
edwardpro
  • 浏览: 310122 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

thrift-1-2-3

阅读更多

国庆前后玩了一下thrift,下面是一些入门级的体会和心得:

 

1 在linux 64位下的编译过程,之前已经写过一个文章了:http://edwardpro.iteye.com/blog/1172064

 

 

2 客户端体系结构:

 

thrift在客户端中几个大的部分:

 

TTransport -> TTProtocol -> {生成的业务代码}

 

这三者是一个引用关系,简单说:

TTransport:代表了用什么方式和远端通讯,在thrift官方包中我使用的是TSocket,本质上就是通过socket来进行通讯

TTProtocol:协议层,协议层是指说话的语言,比如可以使用json也可以使用SImpleJson,当然效率最高的我想应该是Bin模式,它在每次发送的头部都有一个版本字段的,这应该是我们通常协议设计的一些基础思想。

业务代码:通过描述生成的,简单说就是调用协议层和远程说话,至于怎么说,是打电话呢还是发短信呢就是有TTransport来指挥的,这样说大家应该基本上能记住这玩意了。

生成代码类中有几个比较重要的static class,大家需要知道的:

1) iface 也就是你描述的方法生成的对应接口

2)Client,也就是你可以用来new的客户端对象

 

3 服务器体系:

 

服务器体系我没有太多研究也就是知道大概用法,首先需要对你服务接口里的iface做implements,实现功能,如这次开发的实现:

 

class TestWebThumbServer implements
		thrift.requestWebThumb.Iface {

	@Override
	public WebThumbResult requestSync(String uri) throws TException {
		System.out.println("called by Sync" + uri);
		return null;
	}

	@Override
	public void requestAsync(String uri) throws TException {
		System.out.println("called by Aync" + uri);
	}

}

 

同样Server也包括这样的流程:

TTransport -> handle(你的业务实现) -> Processor

 

			serverTransport = new TServerSocket(8811);
			com.taobao.wireless.webthumb.thrift.requestWebThumb.Iface handle = new TestWebThumbServer();
			Processor<requestWebThumb.Iface> processor = new requestWebThumb.Processor<webthumb.thrift.requestWebThumb.Iface>(
					handle);
			TServer server = new TThreadPoolServer(new TThreadPoolServer.Args(
					serverTransport).processor(processor));
			server.serve();

 TTransport: 同样担负着协议部分的重要责任

handle:你的实现

Processor:业务处理线程,用来做一个类似Selector的模式(这个问题后面数落的时候会说)

 

4 客户端基本使用过程:

 

1) 根据描述文件生成最初的代码

2) 接下来就是写代码了,其实说起来是很容易的,但是并不是这样的,因为你万事得考虑一个效率和易用性:

 

先说易用性:

 

易用性在我的实现里采用了代理模式,考虑调用代码基本上每个方法调用都是一个模型,因此为了使用方便不重复劳动,因此使用了代理模式,当然了代理模式个人还是很清醒低认识到这玩意对jvm的性能是有伤害的,不过这个实现思路比较简单,当然代码量是不小的,因为我还是用的jdk原生的反射,这些构造函数到方法一步步的处理代码还是很多的,而且有很多异常要判断。

然后在代码里你只需要声明一个虚拟的接口,这个接口生成服务就可以了比如:

public interface WebthumbServiceInternal {
	
	@ClassName(name="requestWebThumb$Client")
	@MethodName(name="requestAsync")
	public void request(String uri);
}

 接下来是性能:

首先我们看到了TSocket这个transport是一个block io设计,所以为了更高效率执行和避免服务器被搞死,我做了一个以服务器为单位的线程池(Executor)来完成这项工作,但在使用时发现一个问题,本来以为连接可以不断开,但实际上在多线程下访问同一个socket,即使你控制了线程还是不行:

会返回一个叫:broken pipe的错误,可以确认线程执行没问题,没有出现污染。经过查阅资料,是说linux下的socket连接会禁止多线程访问,这也就是当你手工连续执行两个方法的时候,是可以的,但是当你用单线程来控制就不行了(因为不同的runnable是属于不同的线程的)

 

因此要解决这个问题就需要使用nio了,我使用的是netty,netty里是通过channel来控制的,channel本质上看起来更像是一个资源会话。所以当我们使用非阻塞的时候发现很多代码要变了:

1) 需要建立一个接收缓冲池

2)channel本身不需要更多的线程管理了,可以通过设置option来解决

3)执行的时候不需要再自己控制所谓的executor了,因为netty帮你做了

 

当然经过了一个晚上的编码,直到天亮,直到看到只有ip4s没有传说中的ip5的时候还是有一个诡异的问题没有解决,当我通过bootstrape连接上去的时候,很奇怪,总是会被服务器踢掉,导致后续的channel就算自己connect也不行了(案例来说应该可以的,但是就是不行),这个问题还没搞定,应该是用netty上有点问题,对netty的pipe也要更多研究下,后面有结果再向大家汇报。

 

接下来我想讲讲自己对thrift的一些感觉:

 

优点:

 

1 发现thrift的通讯是双向的,在Transport中可以制定out和in不同的流,这两者可以分开指定,意味着这玩意已经不再局限在我们所看到的单向rpc模式,而是可以通过自己双手改造成一个双向服务器,而这个对于一些压力非常高的请求就非常必要,比如我们平时在用的tair,就是这样的设计形态(当然它没有oneway是蛮suck的)

 

2 设计层次我前面讲过了,不重复,我觉得在可扩展性上还是不错的,很好用,接口设计都比较清晰,一看源代码就很清楚。

 

 

缺点:

 

 

1 bug太多了,我经过两个晚上已经发现的bug有:

 

Tserver的强壮性很差,特别是我故意发送一些不对的字节流时会出现但是又不是100%,这个看起来应该是processor的问题了,不过因为netty没搞定,心情上没去深入搭理这个问题。

 

Protocol中的Json协议有问题,会引起server端的oom,这个是100%复现的(我使用的是thrift 0.7.0,其他版本为测试不作结论),同样也是因为netty没去查这个thrift的bug。

 

2 自有代码性能不好,这个前面也说了,thrift本身没有实现nio下的持久链接调用这个当今的企业应用环境这个基本上就没有什么实用性了,虽然自己可以写,但是还是希望官方支持下,技术都有小懒的毛病^^

总体来说thrift生成的代码没有太多值得说的地方,包括其生成的接口描述我觉得也是比较混乱,这个也是所有描述型的一个短版,以前soap时代的生成器也大多是这个毛病,不可想象如果生成一个很复杂的服务会是什么情况,所以服务生成真的是有好有坏,如果是内部服务其实效率第一了,这种方案我认为肯定不可取,如果是外部服务在某些情况下是可以考虑的,毕竟这样可以偷懒不少事情,当然这个实际上是根据你的协议设计的,如果协议本身比较复杂的确还是需要的,不然写这个代码姚折腾半天。但是我觉得比较好的方法还是用代理模式,在像java这样的语言里做好框架,然后用代理让客户调用还是很不错的,至少我觉得比生成代码可能要更方便,因为你也得考虑生成代码万一有问题,这个解决起来就费劲了。

 

 

好了关于thrift就说这些,下次解决了netty的问题再来唠叨

 

 

 

分享到:
评论

相关推荐

    thrift-0.13.0.zip

    1. **Thrift IDL**:Thrift IDL文件以`.thrift`为扩展名,用于定义服务、结构体、枚举、常量等。这些定义会被Thrift编译器转换为各种目标语言的代码。 2. **Thrift编译器**:Thrift提供了一个命令行工具,可以根据...

    thrift-0.9.3.exe

    1. **编写Thrift IDL文件**:在.thrift文件中定义服务接口和数据类型。 2. **生成源代码**:运行`thrift-0.9.3.exe`,指定输入的.thrift文件和输出的编程语言(例如,--gen java)。 3. **编译源代码**:将生成的源...

    Laravel开发-thrift-laravel

    1. **集成Thrift**:Thrift-Laravel项目提供了集成Thrift到Laravel的工具和示例,使得开发者可以在Laravel应用中轻松地创建Thrift服务提供商和消费者。 2. **服务提供者**:在Laravel中,服务提供者负责注册和绑定...

    maven-thrift-server

    3. **Thrift服务定义** - 在项目中,通常有一个`.thrift`文件,定义了服务接口和数据结构。例如,`MyService.thrift`可能包含一个`MyService`接口和一些请求/响应类型。 - 接口定义如: ```thrift service ...

    thrift-0.13.0.tar.gz

    1. **源码**:Thrift的核心库和工具的源代码,包括编译器和运行时库,开发者可以深入了解其内部机制并进行定制。 2. **库文件**:预编译好的库文件,适用于不同的操作系统和编程语言,方便快速集成到项目中。 3. **...

    thrift-0.9.0.tar.gz

    1. **数据序列化**:Thrift提供了一种高效的二进制编码格式,用于序列化和反序列化数据,这种格式比XML或JSON更紧凑,更适合网络传输。 2. **跨语言支持**:Thrift支持多种编程语言,如C++, Java, Python, PHP, Ruby...

    thrift-0.13.0在Windows上exe程序.rar

    1. **数据序列化**:Thrift提供了一种高效的二进制编码格式,用于将复杂的数据结构转换成适合在网络上传输的字节流。这使得不同语言的客户端和服务器能够共享数据结构,而无需额外的解析或序列化逻辑。 2. **RPC...

    thrift-parser_2.9.1-2.0.0-M2.zip

    2. **Thrift 解析器**:Thrift 解析器是处理 Thrift IDL 文件的组件,它将 IDL 转换为可执行代码,使得服务之间的通信得以实现。 3. **版本升级**:从 2.9.1 到 2.0.0-M2 表示 Thrift 的一个重大更新,可能引入了新...

    thrift-0.9.1.exe和thrift-0.9.2.exe 含使用说明

    2. **数据类型**:Thrift支持多种基础数据类型,如bool、byte、i16、i32、i64、double、string以及自定义的结构体(struct)和枚举(enum)。 3. **服务实现**:生成的代码提供了服务接口的骨架,你需要在生成的...

    thrift-编译工具

    1. **IDL(接口定义语言)**:Thrift使用类似C++的语法定义服务接口和数据结构,这些定义存储在.thrift文件中。例如: ```thrift service MyService { string sayHello(1:string name) } ``` 2. **编译器**:Thrift...

    thrift-0.9.3 修复版

    1. **链接错误**:这通常发生在编译过程中,当编译器无法找到所需的库或者对象文件时,会出现链接错误。修复可能包括更新或修正了依赖项,或者解决了库文件路径不正确的问题。 2. **兼容性问题**:可能是修复了与...

    thrift文件生成工具thrift-generator.zip

    thrift-generator 是通过 Java 的接口生成 thrift 文件的工具。例子:public interface... list testCase1(1:map, string&gt; arg0,2:list arg1,3:list arg2,4:i64 arg3,5:string arg4)  } 标签:thrift

    common-thrift-bson-3.0.0-M2.zip

    标题 "common-thrift-bson-3.0.0-M2.zip" 和描述 "spring-data-couchbase.zip,couchbase的spring数据集成spring data couchbase" 暗示了本话题涉及两个关键点:Apache Thrift 和 Spring Data Couchbase。Apache ...

    maven-thrift-client

    2. **Thrift IDL 文件**:在 `src/main/thrift` 目录下,编写 Thrift IDL 文件,定义服务接口和数据结构。例如: ```thrift service MyService { string greet(1: string name) } struct Greeting { 1: required...

    thrift-0.9.2.tar.gz

    1. **接口定义语言 (IDL)**:Thrift IDL 允许开发者定义数据结构和服务接口,类似于 Protobuf 或 gRPC。定义的文件通常以 ".thrift" 结尾,这些文件可以被 Thrift 编译器解析生成对应目标语言的代码。 2. **编译器*...

    thrift-0.9.2.exe

    3. **服务器端代码**:根据Thrift IDL自动生成的服务实现,处理客户端请求。 4. **客户端代码**:自动生成的客户端代码,用于调用服务器端的服务。 对于服务器端,你需要实现Thrift编译器生成的抽象接口,创建服务...

    Thrift--JSClient

    1. **Thrift IDL**:介绍Thrift接口定义语言,它是如何定义服务接口和数据结构的,以及如何通过`thrift`编译器将这些定义转换为JavaScript代码。 2. **Thrift协议**:讲解Thrift的二进制传输协议,如何高效地序列化...

    Thrift-0.5.exe

    1. 下载并运行`Thrift-0.5.exe`。 2. 接受许可协议,按照安装向导的提示进行操作。 3. 选择安装目录,通常默认即可。 4. 安装过程中,程序会将Thrift的相关组件复制到指定的目录下。 5. 安装完成后,可能需要设置...

    Thrift-java学习小结

    3. 使用合适的传输层和协议,平衡性能和兼容性需求。 总的来说,Thrift是构建分布式系统和服务通信的强大工具,其简洁的接口定义、高效的协议和跨语言能力,使得它在IT行业中广泛应用。通过深入理解和实践Thrift,...

Global site tag (gtag.js) - Google Analytics