zoukankan      html  css  js  c++  java
  • [编织消息框架][网络IO模型]NIO(select and poll)

    上面测试论证系统内核在read data时会阻塞,如果我们在把第一个阶段解决掉那么性能就会提高

    NIO 编程
    JDK 1.4中的java.nio.*包中引入新的Java I/O库,其目的是提高速度。实际上,“旧”的I/O包已经使用NIO重新实现过,即使我们不显式的使用NIO编程,也能从中受益。速度的提高在文件I/O和网络I/O中都可能会发生,但本文只讨论后者。
    NIO 简介
    NIO我们一般认为是New I/O(也是官方的叫法),因为它是相对于老的I/O类库新增的(其实在JDK 1.4中就已经被引入了,但这个名词还会继续用很久,即使它们在现在看来已经是“旧”的了,所以也提示我们在命名时,需要好好考虑),做了很大的改变。但民间跟多人称之为Non-block I/O,即非阻塞I/O,因为这样叫,更能体现它的特点。而下文中的NIO,不是指整个新的I/O库,而是非阻塞I/O。
    NIO提供了与传统BIO模型中的Socket和ServerSocket相对应的SocketChannel和ServerSocketChannel两种不同的套接字通道实现。
    新增的着两种通道都支持阻塞和非阻塞两种模式。

    由于sun公司出技术要考虑兼容历史问题,所以新的NIO操作添加新的对象,其中比较重要的对象

    1.Channel 通道 

    2.Buffer 缓冲区

    3.Selector 多路复用器

    4.SelectionKey op key


    下面会先对基础知识进行介绍。

    1.通道 Channel
    我们对数据的读取和写入要通过Channel,它就像水管一样,是一个通道。通道不同于流的地方就是通道是双向的,可以用于读、写和同时读写操作。
    底层的操作系统的通道一般都是全双工的,所以全双工的Channel比流能更好的映射底层操作系统的API。而装载数据对象为Buffer
    Channel主要分两大类:
    SelectableChannel:用户网络读写
    FileChannel:用于文件操作

    2、缓冲区 Buffer
    Buffer是一个对象,包含一些要写入或者读出的数据。
    在NIO库中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的;在写入数据时,也是写入到缓冲区中。任何时候访问NIO中的数据,都是通过缓冲区进行操作。
    缓冲区实际上是一个数组,并提供了对数据结构化访问以及维护读写位置等信息。
    具体的缓存区有这些:ByteBuffe、CharBuffer、 ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer。他们实现了相同的接口:Buffer。

    我们只关心ByteBuffe即可


    3、多路复用器 Selector
    Selector是Java NIO 编程的基础。
    Selector提供选择已经就绪的任务的能力:Selector会不断轮询注册在其上的Channel,如果某个Channel上面发生读或者写事件,这个Channel就处于就绪状态,会被Selector轮询出来,然后通过SelectionKey可以获取就绪Channel的集合,进行后续的I/O操作。
    一个Selector可以同时轮询多个Channel,因为JDK使用了epoll()代替传统的select实现,所以没有最大连接句柄1024/2048的限制。所以,只需要一个线程负责Selector的轮询,就可以接入成千上万的客户端。

    4、op key SelectionKey 

    SelectionKey 是socket操作集合,有OP_ACCEPT 接收新的socket连接,OP_CONNECT 客户端连接操作,OP_WRITE 数据写入系统操作,OP_READ 数据准备好

    要注意的是:由于SelectionKey 状态是叠加的,通过Selector定时轮询,会积累多个SelectionKey同多个op key,所以会返回 Set<SelectionKey> 集合,

    当操作完后要删除注册的SelectionKey或清掉状态,这点比较麻烦要开发者自行管理,不太人性

    而返回多个SelectionKey应用层不知道是那个socket来源,所以在OP_ACCEPT同OP_CONNECT 操作时就要调用 attach方法绑定标识,而里面用到黑科技 AtomicReferenceFieldUpdater 感兴趣读者可以看下源码

    小结:通过对象定义跟职责,我们大概组合下如果工作的

    1.能过Selector定时轮询,返回 Set<SelectionKey> 进行分发处理

    2.遍历Set<SelectionKey> 按不同 op key 切分不同handler 分而治之

    3.绑定socet标识,方便提取上下文

    4.处理完成后要向集合 移除 SelectionKey同清理状态

    5.读写数据 channel 通过Buffer处理

     nonblocking I/O 非阻塞模型:如前端比较熟悉的技术ajax轮询

     I/O multiplexing (select and poll) IO多路复用模型:select先阻塞,有活动套接字才返回。与blocking I/O相比,select会有两次系统调用,但是select能处理多个套接字。

    由于每个对象学习成本较大,加上需要相应的工作经验,估计要三四年网络开发编程经验,还有个比较恶心的地方jdk nio有BUG的,以后再介绍。

    了解这些技术起码知道有那些坑,实际使用时能避免出现,解决一个问题时要选择最优方案。

    选择netty框架是种不错的选择,毕竟不是每个人都有能力同充足时间开发的。

  • 相关阅读:
    ABAP接口用法
    监听textarea数值变化
    The first step in solving any problem is recognizing there is one.
    Wrinkles should merely indicate where smiles have been.
    God made relatives.Thank God we can choose our friends.
    Home is where your heart is
    ABAP跳转屏幕
    Python 工具包 werkzeug 初探
    atom通过remote ftp同步本地文件到远程主机的方法
    Mongodb学习笔记一
  • 原文地址:https://www.cnblogs.com/solq111/p/6734123.html
Copyright © 2011-2022 走看看