【netty in action】学习笔记-第一章 了解java NIO(2)

【netty in action】学习笔记-第一章 了解java NIO(2)

上一篇文章了解了java nio的一些特性和基本用法。本篇继续来看看java nio有哪些问题以及netty如何解决这些问题。

跨平台和兼容性问题

java nio有nio和nio2两个版本,后者只支持jdk7。而且java nio本身属于比较low level的api,有时候会遇到在linux运行良好但是在windows上却有问题。

netty提供统一的api,你不需要关注java的版本,也不需要关注操作系统。

ByteBuffer的扩展

通过前面的示例,你能看出来java nio的ByteBuffer并不好用,比如还有自己切换读写模式。netty扩展了ByteBuffer提供更加易用的API。具体的用法在后面章节的笔记中会详细说明。

内存泄漏的问题

nio有个Scattering and Gathering的概念,就是分散读取,集中写入。

image

image
scatter(分散)是指数据从一个channel读取到多个buffer中。比如下面的例子:

ByteBuffer header = ByteBuffer.allocate(128);
ByteBuffer body = ByteBuffer.allocate(1024);
ByteBuffer[] bufferArray = { header, body }
channel.read(bufferArray);

read()方法按照buffer在数组中的顺序将从channel中读取的数据写入到buffer,当一个buffer被写满后,channel紧接着向另一个buffer中写。

集中读的概念就是反过来,多个buffer的数据写入到同一个channel。示例如下:

ByteBuffer header = ByteBuffer.allocate(128);
ByteBuffer body = ByteBuffer.allocate(1024);
ByteBuffer[] bufferArray = { header, body };
channel.write(bufferArray);

java nio提供了专门的接口来处理Scattering and Gathering

public interface ScatteringByteChannel extends ReadableByteChannel
{
    public long read(ByteBuffer[] dsts) throws IOException;

    public long read(ByteBuffer[] dsts, int offset, int length) throws IOException;
}

public interface GatheringByteChannel extends WritableByteChannel
{
    public long write(ByteBuffer[] srcs) throws IOException;

    public long write(ByteBuffer[] srcs, int offset, int length) throws IOException;
}

比如SocketChannel就实现了这两个接口。

image

但是Scattering and Gathering功能会导致内存泄露,一直到Java7才解决内存泄露问题。

epoll的缺陷问题

这是个著名的bug,它会导致Selector空轮询,最终导致CPU 100%。官方声称在JDK1.6版本的update18修复了该问题,但是直到JDK1.7版本该问题仍旧存在,只不过该BUG发生概率降低了一些而已,它并没有被根本解决。

while (true) {
            int selected = selector.select();
            Set<SelectedKeys> readyKeys = selector.selectedKeys();
            Iterator iterator = readyKeys.iterator();
            while (iterator.hasNext()) {
            //do something
            }
        }

解决epoll bug的唯一方法是回收旧的选择器,将先前注册的通道实例转移到新创建的选择器上。而netty正是基于此方法提供的解决方案。

netty 对Selector的select操作周期进行统计,每完成一次空的select操作进行一次计数,若在某个周期内连续发生N次空轮询,则触发了epoll死循环bug。然后netty会重建Selector,判断是否是其他线程发起的重建请求,若不是则将原SocketChannel从旧的Selector上去除注册,重新注册到新的Selector上,并将原来的Selector关闭。

这个问题的详细情况和解决方案,就不做这里展开了,有兴趣的可以网上搜索下。


犀牛饲养员的技术笔记
这个世界上有好人,也有坏人,更多是不好不坏的人。我努力去做一个好人。一直从事java后端开发,架构方...
263 声望
270 粉丝
0 条评论
推荐阅读
总结一些ES不常用的filter
ES内置的token filter很多,大部分实际工作中都用不到。这段时间准备ES认证工程师的考试,备考的时候需要熟悉这些不常用的filter。ES官方对一些filter只是一笔带过,我就想着把备考的笔记整理成博客备忘,也希望...

犀牛饲养员阅读 2.4k

追踪解析 Netty IntObjectHashMap 源码
IntObjectHashMap 是 netty 封装的,key 必须是 int 的 HashMap 容器。在 netty 4 中,该类位于 netty-all 包下的 io.netty.util.collection 路径下;在 netty 5 中,该类位于 netty5-common 包下的 io.netty5.ut...

三流阅读 684

折腾了我一周,原来Netty网络编程就是这么个破玩意儿!!!
1、阻塞阻塞模式下,相关方法都会导致线程暂停ServerSocketChannel.accept 会在没有连接建立时让线程暂停SocketChannel.read 会在通道中没有数据可读时让线程暂停阻塞的表现其实就是线程暂停了,暂停期间不会占用...

紧张的羊肉串aa阅读 565

基于Netty的IM聊天加密技术学习:一文理清常见的加密概念、术语等
在社区中,分享了很多篇基于Netty编写的IM聊天入门文章(比如《跟着源码学IM》系列、《基于Netty,从零开发IM》系列等),在这些文章中分享了各种IM通信算法原理和功能逻辑的实现。但是这样简单的IM聊天系统是比...

JackJiang阅读 545

封面图
netty系列之:在netty中使用proxy protocol
我们知道proxy protocol是haproxy提出的一个代理协议,通过这个协议,所有实现这个协议的proxy或者LBS,都可以附带真实客户端的IP地址和端口号,这使得proxy protocol在实际应用中非常有用。

flydean阅读 464

基于开源IM即时通讯框架MobileIMSDK:RainbowChat-iOS端v6.1版已发布
MobileIMSDK 是一套专门为移动端开发的开源IM即时通讯框架,超轻量级、高度提炼,一套API优雅支持UDP 、TCP 、WebSocket 三种协议,支持iOS、Android、H5、标准Java平台,服务端基于Netty编写。

JackJiang阅读 425

封面图
让我对象告诉你什么是IO、NIO、BIO
stream 仅支持阻塞 API,channel 同时支持阻塞、非阻塞 API,网络 channel 可配合 selector 实现多路复用

紧张的羊肉串aa阅读 422

263 声望
270 粉丝
宣传栏