設置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<SocketChannel>() {           

 @Override

  public void initChannel(SocketChannel ch) throws Exception {

  ch.config().setAllocator(UnpooledByteBufAllocator.DEFAULT);


無論是通過ChannelOption.RCVBUF_ALLOCATOR還是Allocator都只能設置Allocator的類型,無法直接設置ByteBufAllocator分配的ByteBuf類型。下面我們接着分析消息讀取時的ByteBuf分配機制。消息讀取時,調用的是NioByteUnsaferead方法,代碼如下:





首先從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

  • PooledDirectByteBuf

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章