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

【经验总结】NIO常见的陷阱解析

 
阅读更多

NIO编程很容易吗?不容易吗?很容易吗?不容易

吗?……

有些陷阱你需要知道

 

陷阱1:处理事件忘记移除key

在select返回值大于0的情况下,循环处理

Selector.selectedKeys 集合,每处理一个必须移除
Iterator<SelectionKey> it=set.iterator();
While(it.hasNext()){
    SelectionKey key=it.next();
    it.remove(); //切记移除
    ……处理事件
}

不移除的后果是本次的就绪的key集合下次会再次返

回,导致无限循环,CPU消耗100%

 

陷阱2:Selector返回的key集合非线程安全

1、Selector.selectedKeys/keys 返回的集合都是非线程安全的

2、Selector.selectedKeys返回的可移除

3、Selector.keys 不可变

4、 对selected keys的处理必须单线程处理或者适当同步

 

陷阱3:正确注册Channel和更新interest

1、 直接注册不可吗?

      channel.register(selector, ops, attachment);

2、 不是不可以,效率问题

3、 至少加两次锁,锁竞争激烈

4、 Channel本身的regLock,竞争几乎没有

5、 Selector内部的key集合,竞争激烈

6、更好的方式:加入缓冲队列,等待注册,reactor单线程处理

If(isReactorThread()){
     channel.register(selector, ops, attachment);
}
else{
     register.offer(new Event(channel,ops,attachment));
     selector.wakeup();
}

 

7、屏蔽平台差异,避免锁的激烈竞争,采用类似注册channel的方式:

if (this.isReactorThread()) {
    key.interestOps(key.interestOps() | SelectionKey.OP_READ);
}
else {
    this.register.offer(new Event(key,SelectionKey.OP_READ));
    selector.wakeup();
}

 

 

 陷阱4:正确处理OP_WRITE

1、 OP_WRITE处理不当很容易导致CPU 100%

2、 OP_WRITE触发条件

       前提:interest了OP_WRITE

       触发条件:

            socket发送缓冲区可写

            远端关闭

            有错误发生

3 、正确的处理方式

4、 仅在已经连接的channel上注册

5、 仅在有数据可写的时候才注册

6、 触发之后立即取消注册,否则会继续触发导致循环

7、 处理完成后视情况决定是否继续注册

       没有完全写入,继续注册

       全部写入,无需注册

 

 

陷阱5:正确取消注册channel

1、 SelectableChannel一旦注册将一直有效直到明确取消

2、 怎么取消注册?

      channel.close(),内部会调用key.cancel()

       key.cancel();

3 、中断channel的读写所在线程引起的channel关闭

      但是这样还不够!

      key.cancel()仅仅是将key加入cancelledKeys 直到下一次select才真正处理,并且channel的socketfd只有在真正取消注册后才会close(fd)

4、后果是什么?

      服务端,问题不大,select调用频繁

      客户端,通常只有一个连接,关闭channel之后,没有调用select就关闭了selector

      sockfd没有关闭,停留在CLOSE_WAIT状态

      正确的处理方式,取消注册也应当作为事件交给reactor处理,及时wakeup做select

5、 适当的时候调用selector.selectNow()

6、 Netty 在超过256 连接关闭的时候主动调用一次selectNow

 

陷阱6:同时注册OP_ACCPET和OP_READ,同时注册OP_CONNECT和OP_WRITE

1、在底层来说,只有两种事件:read和write

     Java NIO还引入了OP_ACCEPT和OP_CONNECT

     OP_ACCEPT、OP_READ == Read

     OP_CONNECT、OP_WRITE == Write

    同时注册OP_ACCEPT和OP_READ ,或者同时注册OP_CONNECT和OP_WRITE在不同平台上产生错误的行为,避免这样做!

 

陷阱8:NIO的那些bug

 http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6403933

 http://bugs.sun.com/view_bug.do?bug_id=6693490

1、现象:导致已经关闭的连接一直处于就绪状态,select(timeout)不阻塞,CPU消耗100%

     解决:

     升级到jdk 6u4以上版本

     代码上进行规避

2、代码如何规避此bug?

      简单方案:在每次channel.close()之后马上调用select

     Jetty 6的方案:

     当select阻塞时间远远小于设置值

     取消所有interest为0的key

     重新创建Selector并注册有效的key

     还不够健壮,select可能由于中断或者wakeup唤醒,导致误判

     更完善:加入wakeup判断和中断状态判断

     Mina有规避此bug的代码

     Netty3,定期调用selectNow

 

最后忠告

1、 尽量不要尝试实现自己的nio框架,除非有经验丰富的工程师

2、 尽量使用经过广泛实践的开源NIO框架Mina、Netty3、xSocket

3、 尽量使用最新稳定版JDK

4、 遇到问题的时候,也许你可以先看下java的bug database

分享到:
评论
1 楼 无尘道长 2014-11-19  

相关推荐

    NIO的陷阱.docx

    NIO的陷阱,避坑指南

    用NIO解析modbus协议

    用NIO解析modbus协议

    Java_NIO类库Selector机制解析.doc

    Java_NIO类库Selector机制解析.docJava_NIO类库Selector机制解析.docJava_NIO类库Selector机制解析.docJava_NIO类库Selector机制解析.doc

    Java NIO原理解析

    Java NIO原理解析jdk供的无阻塞I/O(NIO)有效解决了多线程服务器存在的线程开销问题,但在使用上略显得复杂一些。在NIO中使用多线程,主要目的已不是为了应对每个客户端请求而分配独立的服务线程,而是通过多线程...

    Java-NIO类库Selector机制解析.docx

    Java_NIO类库Selector机制解析

    Java NIO总结

    Java NIO的总结, 对于新人入门理解很好, 使用Markdown编写

    JavaNIO库Selector机制解析.docx

    JavaNIO库Selector机制解析.docx

    NIO trick and trap .pdf

    NIO陷阱和解读

    JavaNIO chm帮助文档

    Java NIO系列教程(一) Java NIO 概述 Java NIO系列教程(二) Channel Java NIO系列教程(三) Buffer Java NIO系列教程(四) Scatter/Gather Java NIO系列教程(五) 通道之间的数据传输 Java NIO系列教程(六)...

    NIO 入门.chm,NIO 入门.chm

    NIO入门.chm NIO入门.chm NIO入门.chm

    java NIO技巧及原理

    java NIO技巧及原理解析,java IO原理,NIO框架分析,性能比较

    NIO学习总结

    NULL 博文链接:https://qianhao-1987.iteye.com/blog/1457157

    Java_NIO原理解析

    Java NIO非堵塞技术实际是采取Reactor模式,或者说是Observer(观察员)模式为我们监察I/O端口,如果有内容进来,会自动通知我们,这样,我们就不必 开启多个线程死等,从外界看,实现了流畅的I/O读写,不堵塞了。

    java nio 实现socket

    java nio 实现socketjava nio 实现socketjava nio 实现socketjava nio 实现socketjava nio 实现socket

    java NIO和java并发编程的书籍

    java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java...

    Java NIO 中文 Java NIO 中文 Java NIO 中文文档

    Java NIO 深入探讨了 1.4 版的 I/O 新特性,并告诉您如何使用这些特性来极大地提升您所写的 Java 代码的执行效率。这本小册子就程序员所面临的有代表性的 I/O 问题作了详尽阐述,并讲解了 如何才能充分利用新的 I/O ...

    Java NIO系列教程(一) Java NIO 概述

    Java NIO系列教程(一) Java NIO 概述

    Java NIO英文高清原版

    Java NIO英文高清原版

    java nio 包读取超大数据文件

    Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据...

    Java IO NIO and NIO 2 无水印pdf

    Java IO NIO and NIO 2 英文无水印pdf pdf所有页面使用FoxitReader和PDF-XChangeViewer测试都可以打开 本资源转载自网络,如有侵权,请联系上传者或csdn删除 本资源转载自网络,如有侵权,请联系上传者或csdn...

Global site tag (gtag.js) - Google Analytics