设置Netty接收Buff为堆内存模式
转自:https://sanwen8.cn/p/1bfoy1F.html
Netty为了提升报文的读写性能,默认会采用“零拷贝”模式,即消息读取时使用非堆的DirectBuffer来减少ByteBuffer的内存拷贝,如下图所示:
文章图片
如果需要修改接收Buffer的类型,例如从DirectByteBuf修改为HeapByteBuf,首先需要在初始化Channel的时候对接收缓冲区进行设置,客户端代码示例如下:
b.group(group)
.channel(NioSocketChannel.class)
.option(ChannelOption.TCP_NODELAY, true)
.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
.option(ChannelOption.RCVBUF_ALLOCATOR, AdaptiveRecvByteBufAllocator.DEFAULT)
如果是服务端,则需要在链路创建之后,初始化时对Channel的SocketChannelConfig的Allocator属性进行设置,代码如下:
.childHandler(new ChannelInitializer() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.config().setAllocator(UnpooledByteBufAllocator.DEFAULT);
无论是通过ChannelOption.RCVBUF_ALLOCATOR还是Allocator,都只能设置Allocator的类型,无法直接设置ByteBufAllocator分配的ByteBuf类型。下面我们接着分析消息读取时的ByteBuf分配机制。消息读取时,调用的是NioByteUnsafe的read方法,代码如下:
文章图片
首先从SocketChannelConfig中获取ByteBufAllocator,在这里就是UnpooledByteBufAllocator,然后调用它的ioBuffer方法分配内存,它的具体实现如下:
@Override
public ByteBuf ioBuffer() {
if (PlatformDependent.hasUnsafe()) {
return directBuffer(0);
}
return heapBuffer(0);
}
如果非Unsafe模式,则会使用堆内存heapBuffer,接着看hasUnsafe方法实现,它最终会调用如下方法:
文章图片
设置io.netty.noUnsafe属性为true,则默认会使用Heap堆内存创建ByteBuf,下面我们在启动时设置-Dio.netty.noUnsafe为true进行测试
文章图片
设置完成之后,使用Echo程序进行测试,测试结果如下:
文章图片
总结
利用ch.config().setAllocator或Bootstrap.option(ChannelOption.ALLOCATOR, ByteBufAllocator),结合-Dio.netty.noUnsafe,可以灵活的在如下四种ByteBuf之间进行切换:
- UnpooledHeapByteBuf
- PooledHeapByteBuf
- UnpooledDirectByteBuf
- 【设置Netty接收Buff为堆内存模式】 PooledDirectByteBuf
推荐阅读
- 第6.2章(设置属性)
- 15、IDEA学习系列之其他设置(生成javadoc、缓存和索引的清理等)
- performSelectorOnMainThread:withObject:waitUntilDone:参数设置为NO或YES的区别
- spring|spring boot中设置异步请求默认使用的线程池
- Python绘制小红花
- day|day 28 设置路由表
- flutter设置沉浸式状态栏
- Netty|Netty 源码之 FastThreadLocal
- 谷歌/火狐/Safari浏览器设置手机模式浏览
- 自定义dialog在xml设置宽高失效的解决