Netty之ChannelOption的各种参数

  • ChannelOption.SO_BACKLOG, 1024

       BACKLOG用于构造服务端套接字ServerSocket对象,标识当服务器请求处理线程全满时,用于临时存放已完成三次握手的请求的队列的最大长度。如果未设置或所设置的值小于1,Java将使用默认值50。

  ChannelOption.SO_BACKLOG对应的是tcp/ip协议listen函数中的backlog参数,函数listen(int socketfd,int backlog)用来初始化服务端可连接队列,

    服务端处理客户端连接请求是顺序处理的,所以同一时间只能处理一个客户端连接,多个客户端来的时候,服务端将不能处理的客户端连接请求放在队列中等待处理,backlog参数指定了队列的大小

  • ChannelOption.SO_KEEPALIVE, true

      是否启用心跳保活机制。在双方TCP套接字建立连接后(即都进入ESTABLISHED状态)并且在两个小时左右上层没有任何数据传输的情况下,这套机制才会被激活。

  • ChannelOption.TCP_NODELAY, true

 在TCP/IP协议中,无论发送多少数据,总是要在数据前面加上协议头,同时,对方接收到数据,也需要发送ACK表示确认。为了尽可能的利用网络带宽,TCP总是希望尽可能的发送足够大的数据。这里就涉及到一个名为Nagle的算法,该算法的目的就是为了尽可能发送大块数据,避免网络中充斥着许多小数据块。

 TCP_NODELAY就是用于启用或关于Nagle算法。如果要求高实时性,有数据发送时就马上发送,就将该选项设置为true关闭Nagle算法;如果要减少发送次数减少网络交互,就设置为false等累积一定大小后再发送。默认为false。

ChannelOption.TCP_NODELAY参数对应于套接字选项中的TCP_NODELAY,该参数的使用与Nagle算法有关

    Nagle算法是将小的数据包组装为更大的帧然后进行发送,而不是输入一次发送一次,因此在数据包不足的时候会等待其他数据的到了,组装成大的数据包进行发送,虽然该方式有效提高网络的有效

    负载,但是却造成了延时,而该参数的作用就是禁止使用Nagle算法,使用于小数据即时传输,于TCP_NODELAY相对应的是TCP_CORK,该选项是需要等到发送的数据量最大的时候,一次性发送

    数据,适用于文件传输。

4.ChannelOption.SO_REUSEADDR, true

SO_REUSEADDR允许启动一个监听服务器并捆绑其众所周知端口,即使以前建立的将此端口用做他们的本地端口的连接仍存在。这通常是重启监听服务器时出现,若不设置此选项,则bind时将出错。
SO_REUSEADDR允许在同一端口上启动同一服务器的多个实例,只要每个实例捆绑一个不同的本地IP地址即可。对于TCP,我们根本不可能启动捆绑相同IP地址和相同端口号的多个服务器。
SO_REUSEADDR允许单个进程捆绑同一端口到多个套接口上,只要每个捆绑指定不同的本地IP地址即可。这一般不用于TCP服务器。
SO_REUSEADDR允许完全重复的捆绑:当一个IP地址和端口绑定到某个套接口上时,还允许此IP地址和端口捆绑到另一个套接口上。一般来说,这个特性仅在支持多播的系统上才有,而且只对UDP套接口而言(TCP不支持多播)

5.ChannelOption.SO_RCVBUF AND ChannelOption.SO_SNDBUF
定义接收或者传输的系统缓冲区buf的大小,

6.ChannelOption.ALLOCATOR
Netty4使用对象池,重用缓冲区
bootstrap.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
bootstrap.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);

4.EpollChannelOption.SO_REUSEPORT, true


 前几天一个技术群里的小伙伴,

   问netty中.childOption(ChannelOption.SO_RCVBUF,  XX) 

    设置了没有效果, 抓包显示TCP的滑动窗口依然我行我素:) 
    我把我当时的回答再稍加修饰润色一下: 

    第一个误区就是: 

    TCP在三次握手建立连接期间就会通过ACK分组通告自己的初始接收窗口(通告窗口)大小,

   而上边的代码是netty在连接建立成功后才设置的, 所以必然是无效的设置, 

  正确的方法是设置到ServerSocket上, 也就是Option(Option.SO_RCVBUF, XX), 

  一个连接被ServerSocket accept后会clone一个此连接对应的socket, 这个值会继承过来. 



    还有一个误区就是: 

   其实并不是rcv_buf设置多大, 通告窗口就多大的, 他们之间有非比寻常的关系, 

    但绝对不是一一对应的关系, TCP是一种慢启动的协议, linux2.6.39版本之前, 

    在以太网环境中初始通告窗口是的3个MSS(MSS即最大的segment size, 以太网环境中是1460个字 


    节)然后根据拥塞避免算法一点一点增加, 3.x内核初始通告窗口是直接在代码中写死的10个MSS 
    (是google一篇论文的建议). 

    第三点是,

     我担心有人会这么想, 强调下recv_buf并不是个数组啥的(内核buf的数据结构大致是 


    一个segment queue), 也不会预先分配内存, 只是个接收缓冲区size的最大限制, 对端不给 
    你发数据, 内核不会自作多情分配内存给你, 要不然现在动辄单机上百万个长连接就是痴人说梦 
    了 

    总结: 通常情况下, 我个人经验是不建议设置rcv_buf, linux内核会对每一个连接做动态的 
    调整, 一般情况下足够智能, 如果设置死了, 就失去了这个特性, 尤其是大量长连接的应用, 
    我觉得这个设置就忘记吧, 要调优, 也最好到linux内核里面去配置对应参数. 


2.6.32内核代码(/net/ipv4/tcp_input.c): 




2.6.39内核代码(/net/ipv4/tcp_input.c, /include/net/tcp.h): 







原文地址:https://www.cnblogs.com/heroinss/p/9900762.html