重构dubbo-rpc-thrift,走thrift原生协议

学习dubbo有一段时间了,因为公司里,服务端是java,客户端是dotNet,走thrift协议,当时写dubbo-rpc-thrift时是4月份,依赖的dubbo版本最新是2.1.1,那个时候,阿里开源出来的协议里还没有thrift协议,所以只有自己实现。

因为各种原因,今天把dubbo-rpc-thrift又重构了,因为感觉以前的代码不够紧凑,太松散,不够优雅,而且这次公司的项目重构的时间比较长,我也做了其他的项目。现在把手头的项目弄完了,有了空闲时间,再加上前2天把阿里开源出来的thrift协议的实现看了一下,所以今天就动手重构了一下。

目前,GitHub上放的是目前公司内部试用的版本,还没有上过线经过考验,但是里面涉及到需要特别关注的地方基本都有提到。感兴趣的朋友可以去GitHub上,当dubbo-rpc-thrift。
现在一晃,dubbo都到了2.5.1了,这次重构所依赖的就是2.5.1。里面的虽然有thrift协议实现,但不是thrift原生协议,在thrift协议前加了header,破坏了thrift原生协议,这样就成了自己的协议了。如果跨语言的话,最好还是保持thrift原生协议。我们公司里用的thrift原生协议。

这次重构还算不是很难,主要原因是dubbo的解耦解的比较好,API和SPI分的比较清楚,然后做扩展,需要什么,就扩展什么。

实现thrift协议主要改了这些个地方:

1.重写exchange,主要涉及到HeaderExchangeChannel,HeaderExchangeClient,HeaderExchangeServer,HeaderExchanger,HeartBeatTask,Request,凡是涉及到发request的地方,都要重写,假设重写后的请求叫Request2,在发请求的时候,发Request2。主要原因是想用requestId代替TMessage里seqId,但是Request的id是long型的,如果强转为int,那么当id增长到大于int的最大值时,到客户端处理时,拿到的Response的id是long型强转后的int值,在DefaultFuture里就找不到自己的future,可以在客户端这边做缓存,当Request的id大于int型的最大值,或小于int型的最小值时,把long型的RequestId和强转后的int值关联,但是觉得这样不太优雅,而且不及时删除这个缓存有可能引起内存泄露。所以自己就重写了Request2,把里面的INVOKER_ID改为AtomicInteger,其他的都没改,这样的话,Request的id就一直是int型,也可以直接替换TMessage里的seqId。涉及到发送Request的地方全都改成Request2。

2.扩展ProxyFactory,实现ThriftProxyFactory,主要原因用server的逻辑线程做序列化,如果放到codec里,那么用的是netty的work-io线程,这样会导致server端接收和处理请求的TPS降低。thrift里处理是用Processor.process(iprot,oprot),输入流进,输出流出,也就是说,是thrift在内部自己序列化的。在invoker.invoke()时,不用method.invoker,用thrift的Processor.process(iprot,oprot),不用自己序列化。

3.重写Codec,实现ThriftExchangeCodec,序列化用的是thrift自己的TBinaryProtocol。这里有3点注意,第1,thrift客户端没有超时机制,也就是说服务端抛异常或是别的什么,只要是没有响应给thrift客户端,那么thrift客户端就一直等待,第2,就是decodeRequest时,直接把接收的Frame传给invoker,这样减少一次序列化操作,但是<dubbo:protocol> 里配置accesslog="true" 时会报错,因为arguments里必须是primitive类型,第3.thrift协议里的TMessage,只含有方法名,如果客户端同时调用2个方法名相同的方法,会有问题,方法找不到自己所属的interface,这个时候需要保留下每次请求的方法名,接口名。

4.重写Transporter,用netty的LengthFieldPrepender加HeaderLength,和LengthFieldBasedFrameDecoder解析MessageBody。

5.重写protocol,invoder,exporter。这里有个问题要注意:一个端口上只可以暴露一个服务,原因还是thrift里的TMessage里只含有方法名,如果方法名重复了,就找不到所属的interface的名称了,导致后面无法序列化args和result对象。

等到这次重构的测试完了,再把这次重构的版本放到GitHub上,估计还要一个星期左右。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值