`
edwardpro
  • 浏览: 300591 次
  • 性别: 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文件生成工具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

    thrift-typescript:从Thrift IDL文件生成TypeScript

    2 : required bool field1, # 3 : required string field, 4 : required i16 field, } 您可以通过命令行生成TypeScript: $ thrift-typescript --target apache --rootDir . --sourceDir thrift --outDir ...

    thrift-zookeeper-rpc

    对于Thrift服务化的改造,主要是客户端,可以从如下几个方面进行: 1.服务端的服务注册,客户端自动发现,无需手工修改配置,这里我们使用zookeeper,但由于zookeeper本身提供的客户端使用较为复杂,因此采用curator...

    laravel-thrift-zipkin-project:基于thrift zipkin链路监控

    Zipkin使用安装docker run --name zipkin -d -p...string version(1: string name, 2: zipkin.Options options) throws (1:zipkin.ThriftException ex)}编译服务- Go 使用 thrift -r --gen go:thrift_import=thrift App

    Learning.Apache.Thrift.178588274

    Chapter 3: Running Your First Apache Thrift Service and Client Chapter 4: Understanding How Apache Thrift Works Chapter 5: Generating and Running Code in Different Languages Chapter 6: Handling Errors...

    编译后的thrift客户端

    编译后的thrift客户端,已经经过公司师父同意分享。 1. cp /Users/dxm/Desktop/thrift /usr/local/bin/ 2. echo $PATH 3. thrift 4. chmod +x /usr/local/bin/thrift 5. thrift 6. thrift -version

    thrift-service-framework:一个基于facebook thrift rpc框架的服务框架,支持http rpc js客户端调用

    支持以servlet方式嵌入web容器(tomcat/weblogic/jboss之类)运行2、 也可以直接用嵌入式jetty直接从jar包运行###支持javascript调用支持js直接调用,post的json格式为:以下格式无需手动拼写,thrift生成的js客户端会...

    c++开发环境资源包.txt

    boost_1_55_0.tar.bz2 dev_env.sh gperftools.tar.gz libpcap-1.4.0.tar.gz mongo-c-driver-0.8.1 openssl-1.0.2j.tar.gz redis_baic.conf thrift-0.9.0.tar.gz boost_1_55_0.tar.gz dpkt-1.8.tar.gz impacket-...

    workerman-thrift:基于workermanPHP Thrift RPC

    工人 ... 多进程 支持TCP / UDP ...1,下载或git clone https://github.com/walkor/workerman-thrift 2,运行composer install 启动停止 以ubuntu为例 启动php start.php start -d 重启启动php start.php r

    php-thrift-mapper:将PHP数组转换为Apache Thrift结构类型

    struct Bonk{ 1: string message, 2: i32 type}生成如下所示PHP源代码。 class Bonk { static $ _TSPEC ; /** * @var string */ public $ message = null ; /** * @var int */ public $ type = null ; public ...

    php-thrift-impala:PHP Thrift Client for Impala查询

    Impala-通过Impala Service Thrift接口扩展Beeswax协议。 使用范例 // Load this lib require_once __DIR__ . '/vendor/autoload.php' ; // Try out an Impala query $ impala = new \ ThriftSQL \ Impala ( 'hd-...

    thrift-laravel:对laravel的工匠勤俭节约

    服务器端shell&gt; php artisan thrift:demo:server服务器端会要求选择 单进程和多进程模式1: 单进程模式2: 多进程模式客户端shell&gt; php artisan thrift:demo:client注意:运行本项目之前,需要执行 composer ...

    HARPC简介1

    (2) thrift --gen java demo.thrift (3) 项目目录结构 (2) thrift --gen py tutorial.thrift

    thrift-scala-type-provider:这是使用 Scala 的注释宏功能为 Thrift 创建 Scala 类型提供程序(参见 F#​​)的尝试

    Scala Thrift 类型提供程序 ###用法: @fromSchema("myThrift.thrift") object ChatIDL val msg = ChatIDL.Message("Hello") object MyImpl extends ChatIDL.... 2: list&lt;string&gt; aa 3: Elem i 4: set&lt;bool&gt; bb

    xmljava系统源码-dubbo-thrift:改自yankai913的项目

    (thrift2(?),thrift093(建议在系统里都使用这个协议),swift(暂时不支持)),以原生协议提供服务. thrift0.9.1之后开始支持多路复用;这里我新增的部分没有使用这一特性,所以理论上是支持从thrift0.8.0--thrift0.9.3之间...

    thrift的各种服务和各种源代码

    支持js直接调用,post的json格式为: 以下格式无需手动拼写,thrift生成的js客户端会自动封装及解析 [1,"hello",1,0,{"1":{"str":"jimmy"}}] 返回结果以json格式返回: [1,"hello",2,0,{"0":{"str":"hello,jimmy"}}] ...

    thrift2flow:将Thrift规范转换为Flow JavaScript类型定义

    thrift2flow 自动将规范转换为类型定义文件! 注意:该库尝试与 JS语义保持一致,这意味着它可能与apache thrift项目生成的代码不兼容。 例子: typedef string UUID struct Customer { 1: UUID id 2: string ...

    在php的yii2框架中整合hbase库的方法

    Hbase有两套thrift接口(thrift1和thrift2),但是它们并不兼容。根据官方文档,thrift1很可能被抛弃,本文以thrift2整合为例。 1、访问官网http://thrift.apache.org/download,下载 thrift-0.11.0.exe (生成...

    hbase-sdk是基于hbase-client和hbase-thrift的原生API封装的一款轻量级的HBase ORM框架

    对HBase的API做了一层抽象,统一了HBase1.x和HBase2.x的实现,并提供了读写HBase的ORM的支持,同时,sdk还对HBase thrift 的客户端API进行了池化封装,(类似JedisPool),消除了直接使用原生API的各种问题,使之...

    C#通过thrift连接hbase操作步骤

    1、 下载thrift-0.9.1.exe和源码包thrift-0.9.1.tar.gz  2、利用thrift-0.9.1.exe工具生成thrift连接hbase的客户端接口代码:  从hbase源码包目录  hbase-0.96.0-srchbase-0.96.0hbase-...

Global site tag (gtag.js) - Google Analytics