关于netty:netty-in-action学习笔记第一章-了解java-NIO2

4次阅读

共计 1941 个字符,预计需要花费 5 分钟才能阅读完成。

【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 的概念,就是扩散读取,集中写入。


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 就实现了这两个接口。

然而 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 敞开。

这个问题的详细情况和解决方案,就不做这里开展了,有趣味的能够网上搜寻下。

正文完
 0