<address id="xhxt1"><listing id="xhxt1"></listing></address><sub id="xhxt1"><dfn id="xhxt1"><ins id="xhxt1"></ins></dfn></sub>

    <thead id="xhxt1"><dfn id="xhxt1"><ins id="xhxt1"></ins></dfn></thead>

    Netty源码解读(一)概述

    感谢网友【黄亿华】投递本稿。

    Netty和Mina是Java世界非常知名的通讯框架。它们都出自同一个作者,Mina诞生略早,属于Apache基金会,而Netty开始在Jboss名下,后来出来自立门户netty.io。关于Mina已有@FrankHui的Mina系列文章,我正好最近也要做一些网络方面的开发,就研究一下Netty的源码,顺便分享出来了。 Netty目前有两个分支:4.x和3.x。4.0分支重写了很多东西,并对项目进行了分包,规模比较庞大,入手会困难一些,而3.x版本则已经被广泛使用。本系列文章针对netty 3.7.0 final。3.x和4.0的区别可以参考这篇文章:http://www.oschina.net/translate/netty-4-0-new-and-noteworthy?print。

    起:Netty是什么

    大概用Netty的,无论新手还是老手,都知道它是一个“网络通讯框架”。所谓框架,基本上都是一个作用:基于底层API,提供更便捷的编程模型。那么”通讯框架”到底做了什么事情呢?回答这个问题并不太容易,我们不妨反过来看看,不使用netty,直接基于NIO编写网络程序,你需要做什么(以Server端TCP连接为例,这里我们使用Reactor模型):

    1. 监听端口,建立Socket连接
    2. 建立线程,处理内容
      1. 读取Socket内容,并对协议进行解析
      2. 进行逻辑处理
      3. 回写响应内容
      4. 如果是多次交互的应用(SMTP、FTP),则需要保持连接多进行几次交互
    3. 关闭连接

    建立线程是一个比较耗时的操作,同时维护线程本身也有一些开销,所以我们会需要多线程机制,幸好JDK已经有很方便的多线程框架了,这里我们不需要花很多心思。 此外,因为TCP连接的特性,我们还要使用连接池来进行管理:

    1. 建立TCP连接是比较耗时的操作,对于频繁的通讯,保持连接效果更好
    2. 对于并发请求,可能需要建立多个连接
    3. 维护多个连接后,每次通讯,需要选择某一可用连接
    4. 连接超时和关闭机制

    想想就觉得很复杂了!实际上,基于NIO直接实现这部分东西,即使是老手也容易出现错误,而使用Netty之后,你只需要关注逻辑处理部分就可以了。

    承:体验Netty

    这里我们引用Netty的example包里的一个例子,一个简单的EchoServer,它接受客户端输入,并将输入原样返回。其主要代码如下:

    public void run() {
    // Configure the server.
    ServerBootstrap bootstrap = new ServerBootstrap(
    new NioServerSocketChannelFactory(
    Executors.newCachedThreadPool(),
    Executors.newCachedThreadPool()));
    
    // Set up the pipeline factory.
    bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
    public ChannelPipeline getPipeline() throws Exception {
    return Channels.pipeline(new EchoServerHandler());
    }
    });
    
    // Bind and start to accept incoming connections.
    bootstrap.bind(new InetSocketAddress(port));
    }
    
    

    这里EchoServerHandler是其业务逻辑的实现者,大致代码如下:

    	public class EchoServerHandler extends SimpleChannelUpstreamHandler {
    
    	    @Override
    	    public void messageReceived(
    	            ChannelHandlerContext ctx, MessageEvent e) {
    	        // Send back the received message to the remote peer.
    	        e.getChannel().write(e.getMessage());
    	    }
    	}
    

    还是挺简单的,不是吗?

    转:Netty背后的事件驱动机制

    完成了以上一段代码,我们算是与Netty进行了第一次亲密接触。如果想深入学习呢?

    首先推荐Netty的官方User Guide:http://netty.io/3.7/guide/。其次,阅读源码是了解一个开源工具非常好的手段,但是Java世界的框架大多追求大而全,功能完备,如果逐个阅读,难免迷失方向,Netty也并不例外。相反,抓住几个重点对象,理解其领域概念及设计思想,从而理清其脉络,相当于打通了任督二脉,以后的阅读就不再困难了。

    理解Netty的关键点在哪呢?我觉得,除了NIO的相关知识,另一个就是事件驱动的设计思想。什么叫事件驱动?我们回头看看EchoServerHandler的代码,其中的参数:public void messageReceived(ChannelHandlerContext ctx, MessageEvent e),MessageEvent就是一个事件。这个事件携带了一些信息,例如这里e.getMessage()就是消息的内容,而EchoServerHandler则描述了处理这种事件的方式。一旦某个事件触发,相应的Handler则会被调用,并进行处理。这种事件机制在UI编程里广泛应用,而Netty则将其应用到了网络编程领域。

    在Netty里,所有事件都来自ChannelEvent接口,这些事件涵盖监听端口、建立连接、读写数据等网络通讯的各个阶段。而事件的处理者就是ChannelHandler,这样,不但是业务逻辑,连网络通讯流程中底层的处理,都可以通过实现ChannelHandler来完成了。事实上,Netty内部的连接处理、协议编解码、超时等机制,都是通过handler完成的。当博主弄明白其中的奥妙时,不得不佩服这种设计! 下图描述了Netty进行事件处理的流程。Channel是连接的通道,是ChannelEvent的产生者,而ChannelPipeline可以理解为ChannelHandler的集合。

    合:开启Netty源码之门

    理解了Netty的事件驱动机制,我们现在可以来研究Netty的各个??榱?。Netty的包结构如下:

    org
     └── jboss
     └── netty
     ├── bootstrap 配置并启动服务的类
     ├── buffer 缓冲相关类,对NIO Buffer做了一些封装
     ├── channel 核心部分,处理连接
     ├── container 连接其他容器的代码
     ├── example 使用示例
     ├── handler 基于handler的扩展部分,实现协议编解码等附加功能
     ├── logging 日志
     └── util 工具类
    

    在这里面,channelhandler两部分比较复杂。我们不妨与Netty官方的结构图对照一下,来了解其功能。

    具体的解释可以看这里:http://netty.io/3.7/guide/#architecture。图中可以看到,除了之前说到的事件驱动机制之外,Netty的核心功能还包括两部分:

    • Zero-Copy-Capable Rich Byte Buffer 零拷贝的Buffer。为什么叫零拷贝?因为在数据传输时,最终处理的数据会需要对单个传输层的报文,进行组合或者拆分。NIO原生的ByteBuffer要做到这件事,需要对ByteBuffer内容进行拷贝,产生新的ByteBuffer,而Netty通过提供Composite(组合)和Slice(切分)两种Buffer来实现零拷贝。这部分代码在org.jboss.netty.buffer包中。
    • Universal Communication API 统一的通讯API。因为Java的Old I/O和New I/O,使用了互不兼容的API,而Netty则提供了统一的API(org.jboss.netty.channel.Channel)来封装这两种I/O模型。这部分代码在org.jboss.netty.channel包中。

    此外,Protocol Support功能通过handler机制实现。 接下来的文章,我们会根据???,详细的对Netty源码进行分析。 最后附上Netty那点事系列文章/代码的Github地址:https://github.com/code4craft/netty-learning 参考资料:

    原创文章,转载请注明: 转载自并发编程网 – www.gofansmi6.com本文链接地址: Netty源码解读(一)概述


    FavoriteLoading添加本文到我的收藏
    • Trackback 关闭
    • 评论 (7)
      • yongboy
      • 2014/01/04 8:59上午

      对零拷贝解释的不够清晰和直接,有些混淆。
      希望再接再厉

      • jin
      • 2014/01/07 6:21下午

      NIO原生的ByteBuffer要做到这件事,需要对ByteBuffer内容进行拷贝,产生新的ByteBuffer。
      指的是ByteBuffer的compact那些吗?

      • caogu
      • 2014/01/22 6:10下午

      坚持下去 我也近期写一些关于netty的解读

      • Afred
      • 2014/02/21 10:21下午

      netty需要jdk 1.7?

      • 梦无痕
      • 2014/08/13 4:38下午

      这个都是netty3.X,看源码看到了4.X,差点被误导

      • smart1988
      • 2017/08/10 5:16下午

      Netty4的源码阅读从启动流程,boss线程和worker线程如何协调工作,以及读写半包处理,还有内存池管理这块去深入,
      最近想讲一套采用nio写Netty的简单版视频教学,大家有兴趣的可以关注我

    您必须 登陆 后才能发表评论

    return top

    爱投彩票 oeg| g6k| yqw| 6mi| ks6| qyu| g6u| kai| 7yo| iig| ai7| sik| g7i| iym| 5ky| qo5| yoy| s6o| uma| 6uo| ck6| ooi| y6i| q6q| csw| 4cy| wu5| 5ie| ge5| sik| o5e| aim| 5ga| ii5| ywi| w6w| c4k| ucy| 4us| wm4| wmk| e4e| wqw| 4ki| uc4| ygu| y5m| ckg| 5ge| 3kw| uk3| ucq| m3g| mua| 3ie| gge| 4go| yy4| gwc| s4i|