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

一张图说明netty的结构及源码分析后的总结

    博客分类:
  • java
阅读更多
    好久没写技术文章了,根据往深层次学习的大方向,学习了netty的源码,后来女儿出生,太忙也没总结。最近抽空总结一下。

   源码看的是netty3.10版本,担心太新的看不明白。

    简单点都截图了,欢迎交流。

一、netty在我们项目中的位置

查看全图


二、netty的结构图

查看全图



三、说明

1、两大工作

    上图中,主要分左边的chanel部分与右边的pool部分,下面简要分析一下pool中的Boss与Worker的工作。

Boss run(){
1.	可能的epoll bug,重建selector
2.	Sink产生的bind任务
Run(){
		用nio的ServerSocket.bind
		Fire bound状态事件
}
3.处理selector的accept
			找一个worker,用RoundRobin方式依次找。
			把新产生的socketChannel包装一下,new一个registe任务,扔到worker的队列中处理
}


Worker run(){
1.	可能的epoll bug,重建selector
2.	Boss扔过来的,放在queue中channel的registe任务
Run(){
		SocketChannel注册read到selector
		Fire connect状态事件
}
3.处理selector的read
			先用nio的byteBuf,再根据配置的bufFactory产生ChannelBuf
			Fire msg reveive消息事件
}



2. Netty使用与启动例子(org.jboss.netty.example.echo。EchoServer)

        ServerBootstrap bootstrap = new ServerBootstrap(
                new NioServerSocketChannelFactory(
                        Executors.newCachedThreadPool(),
                        Executors.newCachedThreadPool()));
        bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
            public ChannelPipeline getPipeline() {
                ChannelPipeline p = Channels.pipeline();
                if (sslCtx != null) {
                    p.addLast("ssl", sslCtx.newHandler());
                }
                p.addLast("echo", new EchoServerHandler());
                return p;
            }
        });
        bootstrap.setOption("child.tcpNoDelay", true);
        bootstrap.setOption("child.receiveBufferSize", 1048576);
        bootstrap.setOption("child.sendBufferSize", 1048576);
        // Bind and start to accept incoming connections.
        bootstrap.bind(new InetSocketAddress(PORT));


 ServerBootstrap是一个仓库,放置channel工厂与pipeline工厂,还有很多setOption
 New NioServerSocketChannelFactory的时候,就会产生bosspool workerpool以及boss.worker等对象,并且线程已经动起来了。结构图上右侧❶❷就已经好了。在处理channelk前,你们更基础的模块必须组装好,并运转起来,才能开始接生意。
 bootstrap.bind的时候,开始❸new NioServerSocketChannel,配置好它的pipeline,当其包含的jdk的ServerSocketChannek.open后,将fireChannelOpen。在pipleline上handler传递处理
 具体由serverbootsrap的内部类binder处理,它会sendUpstream后,进行channel.bind。这其实是产生一个downStream的bound事件进行处理,最后是pipeline的sink进行处理
 Sink会产生一个bind任务,把真正的jdknio中的操作放boss的queue这里,由boss去做。Boss早就启动好了,就开始在端口监听了。



3.一些要点
1.ChannelHandler的状态管理:
   看多了责任链模式,首先想到ChannelHandler为啥不是单例呢?api中有:
   State management:A ChannelHandler often needs to store some stateful information.The simplest and recommended approach is to use member variables
   api中还有具体的例子可以看。

2.Boss与每一个worker都有自己对应的selector,只关注自己扔进去的channel的特定事件,返回也是这些有变化的channel,这样都是一个单线程中有序运行。多线程中也是组织好的,也不能是无序的,这样线程安全,稳定性,可控性,高性能达到完美。不过selector中的taskQueue用的是ConcurrentLinkedQueue,貌似没看到并发的情况么???放的时候都由boss放,取的时候都在一个线程里。

3.通常我们用底层引用的类,一般包装一下,这样中间过程就有了自己的逻辑了。而selector注册,只能用jdk的channel,这时把包装后的nettychannel当att传进去。这对底层设计或者使用底层,提供了一个范本。

4.在pipeline上产生链式反应时,外部对象调用是fire(channel, event/msg),内部的channelHandler完成工作后,如果调用时是(handlercontext,event/msg)。
   由于pipeline中使用链表,而不是常见的数组,这样context包装handler后就相互之间手拉手了。Context作为内部类对象可以找到外部pipeline对象,再传递到下一个处理。所以类似于j2ee中的filter(filterChain,req/res),要回到链条上来。
   为何用链表呢?因为有up/down两个方向,方便是前,或者后插入。因为handler是交netty用户的。我在druid中看到的是数组放filter,j2ee中的filter是先配置的过滤器先执行,猜测是数组。

5.Jdk nio中是byteBuf对象作为数据缓冲区,netty使用channelBuf,它分两种,一种是直接包装这个byteBuf的。一种是用这个buf产生heap中的对象保存数据。

6.New worker时,它把自己包装成另一个runable,并用静态类方法,使用exactor线程池来启动自己,中间就可以加入一些额外逻辑了。

7. netty中异步处理非常多,比如一个bind,一个注册,都作为任务扔到线程池中处理,异步调用时,产生一个future对象也传过去,作为结果的存放,异步的桥梁。这些操作印象中都会在channel的pipeline上传递一遍,这样的处理方式统一,也方便开发人员扩展功能,也方便用户随便插入中间的处理类。

8. 平时用内部静态类,而这里的DefaultChannelHandlerContext是pipeline的普通一个内部类,实现了一个接口。DefaultChannelHandlerContext当然从属于pipeline,并且它的实例指向pipeline的实例。如果handler处理后回调,就是传过来的ChannelHandler的对象。

9.当boss pool在init()的时候,想要知道内部的boss是不是启动了,就要同步等待。这时候用到一个countDownLatch,虽然实际上一个,按多个boss情况,每一个都要了解,所以countDownLatch属于boss,并且boss正常启动就countDown一下,外部等待的主线程就知道了。这样的设计在druid中也看到了。一般在构建复杂初始化时,主线程需要各自上报自己启动情况,可以这样设计。

10. 我也喜欢在开发一个功能时,把所有用的类,象是单独的机器一样,都预先配置在一个厂房里,如同bootstrap类,然后把相关的类对象都组合好,最后一个init启动起来。
  • 大小: 84.8 KB
  • 大小: 303.9 KB
0
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics