`
m635674608
  • 浏览: 5043433 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

Netty精粹之JAVA NIO开发需要知道的

    博客分类:
  • java
 
阅读更多

学习Netty框架以及相关源码也有一小段时间了,恰逢今天除夕,写篇文章总结一下。Netty是个高效的JAVA NIO框架,总体框架基于异步非阻塞的设计,基于网络IO事件驱动,主要贡献在于可以让用户基于Netty提供的API快速开发高性能、高可靠性的网络应 用。这篇文章主要是介绍Netty框架的基础技术——JAVA NIO。这时候可能会有同学会有点小疑问,是异步IO(AIO)么?然而并不是,虽然JDK7也提供了异步IO(AIO)的接口,但是Netty曾经尝试 过某个小版本,但是效果和NIO相比并没有什么优势,因此后面的版本Netty也把对AIO的支持废弃了,今天我们就来扒一下JAVA NIO。

 

四种IO模型简述

我们先从四种IO模型开始扒起,常见的IO模型有四种(这四种模型在网络上也有很多很多的资料,为较少篇幅本片将这部分内容压缩一下):

  1. 同步阻塞(Blocking IO):最简单的一种IO模型,用户线程在进行IO操作的时候通常是个系统调用,用户线程会由用户空间进入内核空间,内核空间数据包准备好后会将数据拷贝到用户空间,这个时候线程在用户态继续执行。

  2. 同步非阻塞(Non-blocking IO):同步非阻塞IO即在同步阻塞的基础之上将socket设置为NONBLOCK。这样用户线程在发起IO操作之后可以立即返回,但是用户线程需要不断轮询来请求数据。

  3. IO多路复用(IO Multiplexing):即Reactor设计模式,多路复用模型从流程上和同步阻塞的区别不大,主要区别在于操作系统为用户提供了同时轮询多个IO 句柄来查看是否有IO事件的接口(如select),这从根本上允许用户可以使用单个线程来管理多个IO句柄的问题。

  4. 异步IO(Asynchronous IO):即Proactor设计模式。在异步IO模型中,用户不需要去轮询IO事件,然后才进行数据的读取,处理;在异步IO模型中,IO事件就绪的时 候,内核会开启一个独立的内核线程去执行执行IO操作,实现真正的异步IO。这个时候用户线程可以直接读取内核线程准备好的数据。

多路复用IO模型和异步IO模型的区别主要是用户线程得知IO事件的时候在多路复用IO模型中,用户线程需要自己去处理IO,而在异步IO模型中数据已经由内核线程为用户线程准备好了。在实际应用中,在高效的IO应用中,最常见的是第三种IO模型,异步IO目前操作系统方面的支持并不是很好而且在性能数据上并不是很好看。

上面对四种IO模型进行了极其简单的概括,如多读者意犹未尽可以在网上查阅相关资料或者和作者联系。

select、poll和epoll

JAVA对NIO的支持是从1.4版本开始的,是基于多路复用技术,而在linux操作系统方面多路复用技术有三种常用的机制:select、 poll和epoll,epoll的支持也只是linux2.6版本之后才提供,java在jdk5.0的update 9之后才对epoll进行支持。这三种机制本质上都是同步IO,主要是由于他们都需要在读写事件就绪的时候需要自己进行读写,也就是这个这个读写过程是阻 塞的。下面对着三种机制进行简单总结:

  1. select函数:改函数允许进程指示内核等待多个事件中的任何一个发生的时候或者在一定时间之后被唤醒,select有个致命的缺点即在多路复用中文件描述符的数量有限制,如果需要突破限制需要重新编译操作系统内核。

  2. poll函数:poll机制与select机制类似,区别是poll没有最大描述符限制。

  3. epoll函数:epoll在linux2.6内核中被提出来,是之前的select和poll的增强版本。epoll也没有文件描述符数量限制,而且是用一个文件描述符来管理多个描述符。在性能上相比上面两种有了很大的优化。

关于select、poll和epoll的详细介绍可以参考这里

JAVA NIO

JAVA的NIO是基于IO多路复用模型,在不同平台上有不同的实现方式。Linux下面用的是poll和epoll,在BSD上用kqueue,在Windows上是重叠I/O。

在JAVA NIO中有三个核心的组件:Channels、Buffers和Selectors。

JAVA NIO核心组件

在JAVA NIO中,基本上所有的IO都是从Channel开始的,读取操作即从Channel读到Buffer,写操作即从Buffer写入Channel。

NIO读写示意图

 

Channel

在网络IO方面,Channel的主要实现是ServerSocketChannel和SocketChannel。他们都代表一个面向流的可监听 读写事件的socket。ServerSocketChannel是用于服务器端的socket,他提供了一个静态工具方法open来为用户提供获取 Channel的工具:

1
2
3
public static ServerSocketChannel open() throws IOException {
    return SelectorProvider.provider().openServerSocketChannel();
}

其中涉及到的SelectorProvider用于创建具体的Channel,SelectorProvider的获取有三种途径,首先从系统属性 中获取key为java.nio.channels.spi.SelectorProvider的值,如果没有则基于SPI机制来获取,如果再没有则最后 提供默认的,这个默认值跟操作系统平台相关,比如我的mac系统,JDK提供的默认Provider是KQueueSelectorProvider。

ServerSocketChannel提供的接口

ServerSocketChannel的使用方式是面向服务器端的,一般的开发流程是:

  1. 获取一个ServerSocketChannel。

  2. 设置网络操作,这些参数主要是和TCP协议有关。

  3. 将ServerSocketChannel注册到Selector(多路复用器)。

  4. 将ServerSocketChannel和某个具体的地址绑定。

  5. 用户像多路复用器设置感兴趣的IO事件。

  6. 用户线程以阻塞或非阻塞方式轮询Selector来查看是否有就绪的IO事件。

  7. 用户针对不同的IO事件对Channel进行具体的IO操作。

SocketChannel主要是面向客户端的开发的,也是以open方式获取channel,客户端的开发流程大致如下:

  1. 获取一个SocketChannel。

  2. 设置Channel为非阻塞方式。

  3. 获取Selector。

  4. 将channel注册到Selector,并监听CONNECT事件。

  5. 调用channel的connect方法连接指定的服务器和端口。

  6. 如果连接成功则进行IO操作,如果没成功则轮询Selector处理CONNECT事件。

     

Selector

Selector是JAVA NIO中的多路复用器,配合SelectionKey使用,SelectionKey代表着一个Channel和Selector的关系的抽 象,Channel向Selector注册的时候产生,由Selector维护。Selector维护着三个SelectionKey的集合:

key set:这个集合包含所有向Selector注册的Channel产生的SelectionKey,这个集合中的SelectionKey是不能直接被修 改的,除非SelectionKey被channel,并且发生select的时候SelectionKey才被移出。

selected key set:这个集合是key set集合的子集,当有SelectionKey关联的Channel有Channel向Selector注册的IO事件就绪的时候并且有select操 作,对应的SelectionKey会被放到selected key set中。因为这个集合中的SelectionKey可以通过直接调用Set的remove将SelectionKey移除。

cancelled-key:这个集合是也是key set的子集。当有已经向Selector注册的Channel发生degistered的时候,SelectionKey将被放到这个集合,并且在下一次select的时候被从所有的集合中移出。

三种集合的流转我画个图表示一下:

Selector的Selection Key集合流转图

在开发过程中,我们可以将多个Channel注册到一个Selector实例中,用一个线程来处理所有的IO事件,我们也可以将多个Channel注册到多个Selector实例中,结合高效的线程模型可以达到很好的效果。

 

ByteBuffer

JAVA NIO直接和Channel打交道的Buffer是ByteBuffer,ByteBuffer接口提供主要的内存分配、IO读写等相关接口。值得注意的是JAVA NIO提供了两种Buffer内存分配机制,一种是堆内存,另一种是直接内存,主要区别:

  1. 堆内存分配和回收比较快,但是网络数据需要从内核copy到堆中。

  2. 直接内存分配和回收比较慢,但是免去了从内核copy到堆中的一次copy。

这两种内存各有千秋,使用的时候要根据实际情况去选择。

 

总结:

这篇文章主要介绍一下JAVA NIO涉及到的一些基础概念以及JAVA提供的NIO接口进行简单介绍,JAVA NIO提供的接口使用起来,略复杂,实际项目中不建议直接使用JDK提供的API进行开发。Netty是一个基于JAVA NIO开发的可靠的JAVA NIO工具,Netty的精粹我认为除了IO模型之外还有下面的几个部分:

  1. 高效的线程模型

  2. 内存池技术

  3. 零copy技术

Netty是一个优秀的开源NIO框架,我们可以使用它来快速构建高性能的IO服务器,后面我会通过继续深入学习和大家一起分享Netty的实现和原理。

 

http://my.oschina.net/andylucc/blog/614295

分享到:
评论

相关推荐

    NIO netty开发

    netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty...

    Java_NIO框架Netty教程

    资源名称:Java_NIO框架Netty教程资源截图: 资源太大,传百度网盘了,链接在附件中,有需要的同学自取。

    【项目实战】Netty源码剖析&NIO;+Netty5各种RPC架构实战演练三部曲视频教程(未加密)

    Netty是一款基于Java NIO的高性能服务器端编程框架,用于快速开发可维护的网络应用程序。它简化了网络编程的复杂性,使开发者能够更加专注于业务逻辑的实现。Netty提供了事件驱动模型、异步处理能力以及丰富的API...

    Java视频教程 Java游戏服务器端开发 Netty NIO AIO Mina视频教程

    [第4节] JavaNIO流-通道1.flv [第5节] Java NIO流-通道2.flv [第6节] Java NIO流-socket通道操作.flv [第7节] Java NIO流-文件通道操作.flv [第8节] Java NIO流-选择器 .flv [第9节] Java NIO流-选择器操作.flv...

    Java NIO框架Netty教程.pdf

    ### Java NIO框架Netty教程知识点解析 #### 一、Netty框架简介 Netty是一个高性能、异步事件驱动的网络应用框架,用于快速开发可维护的高性能协议服务器与客户端。它提供了对多种协议的支持,如HTTP、WebSocket、...

    Java NIO英文高清原版

    Netty是一个基于NIO的高性能、异步事件驱动的网络应用框架,它简化了网络编程,广泛应用于服务器端应用开发。 NIO的核心概念包括通道(Channel)、缓冲区(Buffer)和选择器(Selector)。以下是对这些核心概念的...

    NIO+Netty5视频教程与Netty源码剖析视频教程

    通过源码剖析,学习者将了解Netty如何利用Java NIO库实现高效的I/O操作,包括Channel、EventLoop、Handler、ByteBuf等关键组件的工作原理,以及Pipeline的事件传播机制。此外,还会涉及Netty的线程模型,如BossGroup...

    Java-NIO-Netty框架学习

    Netty是基于Java NIO构建的一个高性能、异步事件驱动的网络应用框架,常用于开发网络服务器和客户端,如TCP、UDP协议的服务器和客户端,以及HTTP、FTP等高层协议的应用。 Netty的核心设计理念是减少系统开销,提高...

    基于 Netty 开发的 Java 游戏服务端框架,目前提供 CocosCreator 和 Unity 的客户端SDK.zip

    基于 Netty 开发的 Java 游戏服务端框架,目前提供 CocosCreator 和 Unity 的客户端SDK.zip 基于 Netty 开发的 Java 游戏服务端框架,目前提供 CocosCreator 和 Unity 的客户端SDK.zip 基于 Netty 开发的 Java 游戏...

    基于netty的nio使用demo源码

    Netty是一个高性能、异步事件驱动的网络应用框架,它为Java开发人员提供了构建服务器和客户端应用程序的强大工具。NIO(Non-blocking Input/Output)是Java中的一个编程模型,用于处理大量的并发连接,尤其适用于高...

    Java_NIO框架Netty教程.pdf

    Netty是基于Java NIO构建的一个高性能、异步事件驱动的网络应用程序框架,它极大地简化了网络编程,特别是TCP和UDP套接字服务的开发。 Netty的特点: 1. **高度可定制化**:Netty允许开发者自定义各种协议编解码器...

    java_Netty权威指南,详解nio,tcp,http,netty

    Java Netty是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的协议服务器和客户端。这个权威指南深入探讨了Netty的核心概念和技术,同时也涵盖了与网络编程相关的基础,如非阻塞I/O(NIO)、传输...

    java NIO技巧及原理

    Java NIO(New Input/...总之,Java NIO提供了强大的I/O能力,但同时也需要开发者对非阻塞I/O和多路复用有深入理解,才能充分发挥其优势,避免潜在的陷阱。学习和掌握NIO,对于提升Java应用的性能和扩展性至关重要。

    Java网络编程 NIO Netty

    Java网络编程领域中,NIO(Non-blocking Input/Output,非阻塞I/O)和Netty框架是两个关键概念。NIO是一种I/O模型,它与传统的BIO(Blocking I/O)模型不同,BIO在处理连接时一旦进行读写操作就会阻塞,直到数据传输...

    reverse-proxy:通过Netty基于Java NIO的https代理服务器的实现

    通过Netty基于Java NIO的https代理服务器的实现。 这是一个简单的工作原理: 要通过浏览器对其进行测试,我们将需要设置一个虚拟主机名,如下所示: 127.0.0.1 test.localdomain 这样浏览器就能将SNI发送到我们...

    Java NIO Socket基本

    NIO在实际开发中常用于构建高性能的网络服务器,如Tomcat、Netty等框架就大量使用了NIO技术。通过合理使用NIO,开发者可以编写出更加高效、可扩展的服务端代码。了解和掌握Java NIO对于提升Java程序员在服务器端编程...

    netty jar包

    netty 是基于Java NIO的网络通信架构,文件中包含netty所需jar包

    Netty实现Java服务端和C#客户端联通

    开发环境中,Java开发者通常使用IntelliJ IDEA,这是一个强大的集成开发环境,支持Netty插件,方便编写和调试代码。而C#开发者则使用Visual Studio 2017,该IDE对.NET框架和C#提供了全面的支持,包括DotNetty库的...

    java nio&netty系列之三netty网络模型代码以及简化版代码示例

    总的来说,Netty的网络模型基于Java NIO,利用非阻塞I/O和事件驱动的机制,实现了高并发、低延迟的网络通信。同时,Netty提供的API简单易用,使得开发者可以更加专注于业务逻辑,而不是底层的网络细节。结合源码阅读...

Global site tag (gtag.js) - Google Analytics