tcp_nopush和tcp_nodelay

一、tcp_nodelay

避免网络拥堵,tcp协议栈实现了一个Delayed Ack机制;tcp协议规定接受到一个数据时,必须要发送一个ack作为确认,但是单独发送一个ack代价很高(20字节的ip首部,20字节的tcp首部),所以希望跟随数据一起发送ack;Delayed Ack机制在这里规定了当有响应数据发送时,ack会立刻发送;但是如果没有响应数据,ack确认还是需要发送给对方的,在这里就有一个延迟时间,可以认为是0.2S,超过0.2S后自动发送ack。一个真实的连接会设置MSS参数,因此,TCP/IP希望每次都能够以MSS尺寸的数据块来发送数据,这就引入了Nagle算法。
  Nagle算法就是为了尽可能发送大块数据,避免网络中充斥着许多小数据块。Nagle算法的基本定义是任意时刻,最多只能有一个未被确认的小段。 所谓“小段”,指的是小于MSS尺寸的数据块,所谓“未被确认”,是指一个数据块发送出去后,没有收到对方发送的ACK确认该数据已收到。
为了避免Nagle的捣乱,TCP_NODELAY会强制一个socket发送数据到他的buffer,无论包的大小,当打开一个socket时nginx的参数tcp_nodelay都会把TCP_NODELAY函数加进去。此参数允许禁止Nagle算法,尽可能快的发送数据,nginx使用tcp_nodelay在HTTP keepalive长连接中,keepalive会在发送数据后保持打开一段时间,允许在三次握手后不需要初始化一个连接仍能发送更多的数据,并在每次数据转换后保持连接状态不切换到FIN_WAIT状态。
当然了实际生产上,更合理的方式是应该使用一次大数据的写操作而不是多次小数据的写操作。
有关delay ack和Nagle请移步:http://www.tuicool.com/articles/YfM7nm

二、tcp_nopush

  在nginx中,配置参数tcp_nopush的作用和tcp_nodelay是互斥的,这个参数不是优化延迟而是数据发送的优化。tcp_nopush参数在LINUX协议栈中会调用TCP_CORK方法,TCP_CORK会阻塞数据直到包达到MSS才会发送出去;这个标准的大概的意思是,一般情况下,在tcp交互的过程中,当应用程序接收到数据包后马上传送出去,不等待,而tcp_cork选项是数据包不会马上传送出去,等到数据包最大时,一次性的传输出去,这样有助于解决网络堵塞,已经是默认了,注意,tcp_nopush只在sendfile开启时才有效。详见下图
tcp_nopush和tcp_nodelay

  以快递投递举例说明一下(以下是我的理解,也许是不正确的),当快递东西时,快递员收到一个包裹,马上投递,这样保证了即时性,但是会耗费大量的人力物力,在网络上表现就是会引起网络堵塞,而当快递收到一个包裹,把包裹放到集散地,等一定数量后统一投递,这样就是tcp_cork的选项干的事情,这样的话,会最大化的利用网络资源,虽然有一点点延迟。
有关sendfile,请移步:http://www.52devops.com/chuck/1354.html

三、生产使用建议

全都开启,即
sendfile on
tcp_nopush on
tcp_nodelay on
混合使用这三个参数确保包被发送到客户端时是完整的,还能很大程度上降低网络拥堵。tcp_nopush可以和tcp_nodelay一起使用,并且此设置是优先于tcp_nodelay的。
TCP_CORK can be set together with TCP_NODELAY and it is stronger than TCP_NODELAY.
源码学习请移步:http://elixir.free-electrons.com/linux/latest/source/net/ipv4/tcp.c#L2525

0
未经许可,不得转载,否则将受到作者追究,博主联系方式见首页右上角

该文章由 发布

这货来去如风,什么鬼都没留下!!!
发表我的评论
取消评论
代码 贴图 加粗 链接 删除线 签到

(1)条精彩评论:
  1. 匿名
    大神,请收下我的膝盖。
    匿名2017-06-09 15:54 回复