Netty源码分析 之 实现原理

个人觉得Netty之所以高性能主要是因为它的多路I/O复用模型和零拷贝的Buffer。

Netty中有两大核心组件ChannelFactory与ChannelPipeline,可以说Netty的整个架构的核心都是靠这两大组件支撑起来的。

 

Netty的网络模型(ChannelFactory)



 

ChannelFactory有两组线程池BossPoolWorkerPoolBossPool相对上图的mainReactor负责接受连接请求,workerPool对应上图的SubReactorThreadPool部分,用于处理自身任务队列、读、写等操作。

BossPool工作线程接受到连接后,将此连接交给workerPoolworkerPool监听并处理此连接的读写事件.

下面看一下Netty的网络模型实现原理

ChannelFactory接口

它负责创建Channel

 

NioServerSocketChannelFactory

实现自ChannelFactory接口,服务器端的Channel工厂

 

NioClientSocketChannelFactory

实现自ChannelFactory接口,客户端的Channel工厂

这两个实现类中都维护了3个对象bossPoolworkerPoolsink;

sink:则对应PipeLine设计模式(下面会了解到)中的sink部分;

 

下面是ChannelFactory的基本原理图(有些类,有些方法看不懂没事,源码分析的时候会了解到)



 

Thread Pipeline设计模式

 

关于此设计模式的思想请参看此PPThttp://febird.googlecode.com/svn-history/r515/trunk/febird/doc/multi_thread_pipeline_cn.pptx

这个PPT讲得可能有点抽象,我举个包子解释一下:

Pipeline可以看成是生产车间的一条生产流水线,原材料(数据)经过流水线中的每一道工序加工(也就是Handler)最终成为一个产品,每道工序由不同的人(Thread)干,有的工序复杂做得比较慢,有的工序简单做得比较快,但是一个产品必需等到所有工序都加工完后才能进行组装出厂(sink所干的事)。

 

WorkThreadPool:有了生产线流水线那谁来负责生产呢?工人。如果把工人看成是一个Thread那么一个生产车间里的所有工人组成的集合可以看成是ThreadPool。正常情况下,一个工人往往会被分配很多的原材料(数据),但一个工人每次只能加工一个原材料(假设是这样),因此必需要有一个池子(任务排队)来保证工人们正常完成工作,工人的工资一般与自己加工的产品量挂钩,如果大家都从这个池子里拿原材料加工将很有可能会导致冲突(线程同步导致的阻塞),因此厂里给每个工人按月给定一定的数量的任务(WorkThread有了自己的队列),这样每个工人各自完成各自的任务,几乎不会有竞争。

ChannelPipeline的默认实现类是DefaultChannelPipeline,各个被注册到Pipeline中的ChanelHandler都是在同一个工作线程中执行的,不会被拆分到多个线程中去,DefaultChannelPipeline中维护的是一个单向前后节点相连的链表的首尾指针(head,tail),此链表的数据结构如图:



 

当底层NIO触发“读”事件的时候将从head节点开始执行如下动作:

1、判断当前节点的Handler是否实现了ChannelUpstreamHandler接口

             a)如果是则执行其handleUpstream(ctx, e)

             b)否则继续向查找next直到为next为null

 

当代码调用channel.write方法后将从tail节点开始执行如下动作:

1、判断当前节点的Handler是否实现了ChannelDownstreamHandler接口

             a)如果是则执行其handleDownstream(ctx, e)

             b)否则继续查找prev直到为prev为null

             c)当上面两种情况在执行的时候,如果当前节点的prev为null的时候则执行此Pipeline中sink对象的eventSunk方法做关闭、绑定、链接、写数据等操作



 

 

 

 从图中可以看出底层NIO触发read事件将触发PipelineUpstream直到最后的Hhandler处理完成(这里通常做解码操作)后丢弃;当用户代码调用Channelwrite方法后将触发PipelineDownStream直到最前面的Handler处理完后(这里通常做编码操作)再执行底层Socketwrite操作。

自定义的ChannelHandler可以控制是否继续执行后续的handler。这点很像Spring中的ReflectiveMethodInvocation

猜你喜欢

转载自xuyunti.iteye.com/blog/2288498