③tcp_nodelay(一次尽可能发出数据,而非缓冲区缓存;禁用nagle算法)
参考文章:ChannelOption.TCP_NODELAY, true->浅谈tcp_nodelay的作用
来源:属于 SocketChannal 参数。
说明:为了尽可能发送大块数据,避免网络中充斥着许多小数据块。根据某个算法会先对要发的数据进行攒一批之后一次发送出去。默认设置的是false(开启的nagle算法),实际希望消息尽快发出去,所以要设置其为true。(对于想要测试出效果,目前没有找到合适的例子)
.option(ChannelOption.TCP_NODELAY,true)
④so_sendbuf & so_rcvbuf(发送缓冲区和接收缓冲区)
来源:SO_SNDBUF 属于 SocketChannal 参数;SO_RCVBUF 既可用于 SocketChannal 参数,也可以用于 ServerSocketChannal 参数(建议设置到 ServerSocketChannal 上)
目的:设置了滑动窗口的上限。建议不要调整该参数,早期应该根据参数来进行调整,但现在的操作系统比较智能,会自动的根据通信双方的网络能力调整sendbuf和rcvbuf。并不是调的越大越好,若是调的太大可能会对系统内存的占用会比较高!
⑤allocator(配置ctx.alloc()分配的类型和开辟内存空间位置)
参数说明
来源:属于 SocketChannal 参数。
主要目的:配置ctx.alloc()来创建的类型(池化、非池化)与开辟位置(直接、堆)。
默认配置说明:默认是池化直接内存。实际上是根据一个配置类的中配置类型来进行设置的。
配置方式:通过配置虚拟机参数,io.netty.allocator.type=pooled|unpooled来设置池化、非池化。对于直接或堆内依旧使用一个系统变量io.netty.noPrefferDirect=true|false。
测试
直接进行虚拟机参数配置即可:
ch.pipeline().addLast(new ChannelInboundHandlerAdapter(){ @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { log.debug("ctx.alloc() => {}", ctx.alloc().buffer()); } });
源码调试
起点:ChannelConfig
配置池化、非池化参数:io.netty.allocator.type=unpooled|pooled
配置直接、堆内存:io.netty.noPreferDirect=false|true
⑥rcvbuf_allocator(控制netty的接收缓冲区大小。就是在readchannel事件中读到的ByteBuf。)
参数说明+代码示例
来源:属于 SocketChannal 参数。
效果:控制netty的接收缓冲区大小。就是在readchannel事件中读到的ByteBuf。
核心点及默认配置:控制netty的接收缓冲区大小,指的就是最初readchannel中读到的ByteBuf。默认容量为1024,之后实际开辟空间大小跟后面几次传输的实际大小相关,最大为65536,最小为64。
关于类型与开辟空间位置:类型依旧根据根据虚拟机参数io.netty.allocator.type=pooled|unpooled来配置!分配空间位置默认是直接内存,这是固定的不能够更改。(netty认为使用直接内存效率更高)
代码示例
//设置指定的接收ByteBuf大小为100字节 .childOption(ChannelOption.RCVBUF_ALLOCATOR, new FixedRecvByteBufAllocator(100))
测试:
源码分析
切入点:通过设置断点,来根据调用栈找到
其控制池化、非池化:
接着看allocate分配空间方法:
说明:实际由一个分配器来进行创建的ByteBuf。该分配器只能用于配置是池化还是非池化。分配的时候调用的就是ioBuffer,指定就是直接内存,对于容量大小调用的是guess()方法其是猜测出来的,其会动态的根据你几次的数据量来对创建的ByteBuf进行调整,最开始默认是1024,之后若是数据量增多会进行调整,最大不会超过65536。若是穿过来的数据量很小,那么也会进行减少,最小为64。
对于分配的细节,我们需要来查看allocHandle
接着依次查看调用方,确定源头:对应三个参数值对应上面的说明