从本章开始介绍一些netty偏底层的基础知识,了解这些知识对于从原理上可以更好的把握netty以及它为什么会有如此高的性能,ok今天要介绍的缓冲区和管道模型.
1 Bytebuf:缓冲区
其实jdk本身提供了缓冲区,但是有很多的不足,所以netty在此基础之上进行了完善和封装,那么先整体上看看netty实现的缓冲区有哪些优势
优势:
& 可以自定义缓冲区的类型
& 通过内置的复合缓冲类型实现零拷贝
& 不需要调用flip()函数切换读/写模式
& 读取和写入的索引分开了,不像JDK中使用一个索引
& 引用计数
& 内存池
& 动态扩展缓冲区
分类:
HeadBuffer:(堆缓冲)>ByteBuf将数据存储在JVM的堆空间,通过将数据存储在数组中实现的
>>堆缓冲的优点是:分配速度快
>>堆缓冲缺点是:性能较低
DirectBuffer:(堆外加内存)>在堆之外直接分配内存,直接缓冲区不会占用堆的容量
>>优点是:不需要拷贝,性能好
>>缺点是:存储在内存中,分配会更加的耗时和复杂
CompositeByteBuf:(聚合byte)>可以聚合bytebuf,提高性能
实现方式:所有缓冲区都是通过Unpooled这个类来封装好方法的,开发者可以直接调用接口
组合缓冲区:CompositeByteBuf compBuf = Unpooled.compositeBuffer();
堆缓冲区:ByteBuf heapBuf = Unpooled.buffer(8);
直接缓冲区:ByteBuf directBuf = Unpooled.directBuffer(16);
复制缓冲区:ByteBuf directBuf = Unpooled.copiedBuffer(16);
读写机制:
读取:随机访问索引>索引都是从0开始
索引:读写索引分开>writerindex和readerindex
存储区域:0<=readerIndex<=writerIndex<=capacity
>>0<=readerIndex
&& 已经读过的缓冲区
&& 通过调用ByteBuf.discardReadBytes()来回收已经读取过的字节:出现内存的复制,以时间换空间
>>readerIndex<=writerIndex
&& 可读的字节缓冲区
>>writerIndex<=capacity
&& 可写的字节缓冲区
标记Mark和重置reset:
>mark
>>markedReaderIndex:标记读索引:将当前readerIndex备份到markedReaderIndex中
>>markedWriterIndex:标记写索引:将当前readerIndex备份到markedWriterIndex中
>reset
>>resetReaderIndex:将当前readerIndex设置为markedReaderIndex
>>resetWriterIndex:将当前readerIndex设置为markedWriterIndex
ok,上面有关于bytebuf的实现和底层存储读取流程讲讲完了,下面再看
2 管道模型:ChannelPipeline
>Channel:NioServerSocketChannel 和 NioSocketChannel
功能:
网路的读,写,客户端发起连接,主动关闭连接,链路关闭,获取通信双方的网络地址
获取该Channel的EventLoop,获取缓冲分配器ByteBufAllocator和pipeline
>ChannelPipeline
功能:
channel事件消息在ChannelPipeline中流动和传播
用于channel事件的拦截
它是channelhandler的容器
>ChannelHandler:处理每个具体的业务逻辑或者事件
>ChannelHandlerContext
功能:
每个ChannelHandler 被添加到ChannelPipeline 后,都会创建一个ChannelHandlerContext 并与之创建的ChannelHandler 关联绑定
它来处理channelpipele和channlehandler
>ChannelFuture:异步获取i/o执行结果
>ChannelPromise:ChannelPromise是ChannelFuture的扩展,允许设置I/O操作的结果,使ChannelFutureListener可以执行相关操作
>Unsafe:网络i/o基本操作都是由它实现的
到此netty的channel管道模型相关理论知识就讲完了。