Netty 概述

Netty

Tomcat是基于Http协议的,实质是一个基于http协议的web容器; Netty能经过编程自定义各类协议,由于netty可以经过codec本身来编码/解码字节流。
netty的性能不必定比tomcat性能高,tomcat从6.x开始就支持了nio模式,而且后续还有APR模式(一种经过JNI调用apache网络库的模式),相比于旧的bio模式,并发性能获得了很大提升,特别是APR模式。html

为何netty的性能会高呢?

  1. 基于多路复用模型的IO模型下的Reactor模式(事件驱动IO) , 适用于高并发多链接&短而快的IO事件处理 场景。 (多路复用 轮询每一个socket状态是内核在进行的, 传统的NIO是用户线程
  2. 零拷贝. 开辟堆外内存,IO的处理直接在该内存上处理,减小了BIO模型中用户态与内核态的数据复制 ----这个与java提供的原生DirectByteBuffer, 在ByteBuffer 的类注释中有解释
  3. 提供不少减小拷贝的操做
    1. Unpooled.wrappedBuffer  能够将 byte[] 、ByteBuf、ByteBuffer等包装成一个UnpooledDirectByteBuf/UnpooledHeapByteBuf对象(eg. 内部维持了一个byte[],由外部传入的byte[]直接替换), 进而避免了拷贝操做
    2. CompositeByteBuf.addComponents将多个ByteBuf合并为一个逻辑上的ByteBuf。
    3. ByteBuf 支持 slice 操做, 所以能够将 ByteBuf 分解为多个共享同一个存储区域的 ByteBuf, 避免了内存的拷贝
    4. 经过 FileRegion 包装的FileChannel.tranferTo 实现文件传输, 能够直接将文件缓冲区的数据发送到目标 Channel, 避免了传统经过循环 write 方式致使的内存拷贝问题.

      详见: http://www.javashuo.com/article/p-pededtnv-bu.html

支持并发高

基于多路复用的NIO(Nonblocking I/O,非阻塞IO)开发的网络通讯框架,对比于BIO并发性能获得了很大提升。java

BIO的通讯方式

等待客户端发数据这个过程是阻塞的,这样就形成了一个线程只能处理一个请求的状况,而机器能支持的最大线程数是有限的(linux 的unlimit)。linux

NIO的通讯方式

当一个Socket创建好以后,Thread并不会阻塞去接受这个Socket,而是将这个请求交给Selector,Selector会不断的去遍历全部的Socket,一旦有一个Socket创建完成,他会通知Thread,而后Thread处理完数据再返回给客户端。这样就能让一个Thread处理更多的请求了。web

传输快

Netty的传输快其实也是依赖了NIO的一个特性——零拷贝apache

传统数据拷贝

Java的内存有堆内存、栈内存和字符串常量池等等,其中堆内存是占用内存空间最大的一块,也是Java对象存放的地方,通常数据若是须要从IO读取到堆内存,中间须要通过Socket缓冲区,也就是说一个数据会被拷贝两次才能到达他的的终点,若是数据量大,就会形成没必要要的资源浪费。(数据从网卡到内核空间 -> 内核空间再copy到用户空间)编程

零拷贝

Netty当须要接收数据的时候,他会在堆内存以外开辟一块内存,数据就直接从IO读到了那块内存(堆外内存)中去,在netty里面经过ByteBuf能够直接对这些数据进行直接操做,从而加快了传输速度。缓存

封装好

相对于JDK提供的BIO和NIO实现方式,Netty的封装更胜一筹。tomcat

源码解析

几个重要的概念。网络

  • Channel 数据传输流,与channel相关的概念有如下四个
    • Channel,表示一个链接,能够理解为每个请求,就是一个Channel。
    • ChannelHandler,核心处理业务就在这里,用于处理业务请求。
    • ChannelHandlerContext,用于传输业务数据。
    • ChannelPipeline,用于保存处理过程须要用到的ChannelHandler和ChannelHandlerContext。
  • ByteBuf 
    一个存储字节的容器,最大特色就是使用方便,它既有本身的读索引和写索引,方便对整段字节缓存进行读写,也支持get/set,方便对其中每个字节进行读写,数据结构以下图所示:

    有三种使用模式: --类比于JDK提供的ByteBuffer。
    1. Heap Buffer 堆缓冲区
      堆缓冲区是ByteBuf最经常使用的模式,将数据存储在堆空间。
    2. Direct Buffer 直接缓冲区
      直接缓冲区是ByteBuf的另一种经常使用模式,内存分配都不发生在堆,jdk1.4引入的nio的ByteBuffer类容许jvm经过本地方法调用分配内存,这样作有两个好处
      • 经过免去中间交换的内存拷贝, 提高IO处理速度; 直接缓冲区的内容能够驻留在垃圾回收扫描的堆区之外。
      • DirectBuffer 在 -XX:MaxDirectMemorySize=xxM大小限制下, 使用 Heap 以外的内存, GC对此”无能为力”,也就意味着规避了在高负载下频繁的GC过程对应用线程的中断影响.
    3. Composite Buffer 复合缓冲区
      复合缓冲区至关于多个不一样ByteBuf的视图,这是netty提供的,jdk不提供这样的功能。
  • Codec
    能完成字节与pojo、pojo与pojo的相互转换,从而达到自定义协议的目的!!
    在Netty里面最有名的就是HttpRequestDecoderHttpResponseEncoder了。数据结构

相关文章
相关标签/搜索