在TCP/IP协议中,不管发送多少数据,老是要在数据前面加上协议头,同时,对方接收到数据,也须要发送ACK表示确认。为了尽量的利用网络带宽,TCP老是但愿尽量的发送足够大的数据。这里就涉及到一个名为Nagle的算法,该算法的目的就是为了尽量发送大块数据,避免网络中充斥着许多小数据块。node
TCP_NODELAY就是用于启用或关于Nagle算法。若是要求高实时性,有数据发送时就立刻发送,就将该选项设置为true关闭Nagle算法;若是要减小发送次数减小网络交互,就设置为false等累积必定大小后再发送。默认为false。nginx
浅谈tcp_nodelay的做用web
今天在用nginx做web缓存的时候,发如今http里加入这样个参数,能有效的提升数据的实时响应性,那就是tcp_nodelay.下面咱们来讲说tcp_nodelay的原理:算法
TCP_NODELAY和TCP_CORK基本上控制了包的“Nagle化”,这里咱们主要讲TCP_NODELAY.Nagle化在这里的含义是采用Nagle算法把较小的包组装为更大的帧。JohnNagle是Nagle算法的发明人,后者就是用他的名字来命名的,他在1984年首次用这种方法来尝试解决福特汽车公司的网络拥塞问题(欲了解详情请参看IETF RFC 896)。他解决的问题就是所谓的silly window syndrome,中文称“愚蠢窗口症候群”,具体含义是,由于广泛终端应用程序每产生一次击键操做就会发送一个包,而典型状况下一个包会拥有一个字节的数据载荷以及40个字节长的包头,因而产生4000%的过载,很轻易地就能令网络发生拥塞,。Nagle化后来成了一种标准而且当即在因特网上得以实现。它如今已经成为缺省配置了,但在咱们看来,有些场合下把这一选项关掉也是合乎须要的。 apache
如今让咱们假设某个应用程序发出了一个请求,但愿发送小块数据,好比sns游戏中的点击肯定按钮。咱们能够选择当即发送数据或者等待产生更多的数据而后再一次发送两种策略。若是咱们立刻发送数据,那么交互性的以及客户/服务器型的应用程序将极大地受益。例如,当咱们正在发送一个较短的请求而且等候较大的响应时,相关过载与传输的数据总量相比就会比较低,并且,若是请求当即发出那么响应时间也会快一些。以上操做能够经过设置套接字的TCP_NODELAY选项来完成,这样就禁用了Nagle算法,在nginx中设置tcp_nodelay on,注意放在http标签里。编程
另一种状况则须要咱们等到数据量达到最大时才经过网络一次发送所有数据,这种数据传输方式有益于大量数据的通讯性能,典型的应用就是文件服务器。应用Nagle算法在这种状况下就会产生问题。可是,若是你正在发送大量数据,你能够设置TCP_CORK选项禁用Nagle化,其方式正好同TCP_NODELAY相反(TCP_CORK 和 TCP_NODELAY 是互相排斥的)。下面就让咱们仔细分析下其工做原理。 缓存
假设应用程序使用sendfile()函数来转移大量数据(nginx里能够设置sendfile on)。应用协议一般要求发送某些信息来预先解释数据,这些信息其实就是报头内容。典型状况下报头很小,并且套接字上设置了TCP_NODELAY。有报头的包将被当即传输,在某些状况下(取决于内部的包计数器),由于这个包成功地被对方收到后须要请求对方确认。这样,大量数据的传输就会被推迟并且产生了没必要要的网络流量交换。
可是,若是咱们在套接字上设置了TCP_CORK(能够比喻为在管道上插入“塞子”)选项,具备报头的包就会填补大量的数据,全部的数据都根据大小自动地经过包传输出去。当数据传输完成时,最好取消TCP_CORK选项设置给链接“拔去塞子”以便任一部分的帧都能发送出去。这同“塞住”网络链接同等重要。 服务器
总而言之,若是你确定能一块儿发送多个数据集合(例如HTTP响应的头和正文),那么咱们建议你设置TCP_CORK选项,这样在这些数据之间不存在延迟。能极大地有益于WWW、FTP以及文件服务器的性能,同时也简化了你的工做.网络
最近用了用libsoup库,用它来写个HttpServ玩。结果发现性能不行,居然比nginx/apache慢了20倍。拿wireshark一看,发现每一个TCP回复都要耗时几百毫秒。这就一会儿让我想到了Nagle算法(通常的Nagle算法都是延时200ms)。因而下载libsoup的库,看代码,果真没有setsockopt。因而设置了TCP_NODELAY,结果速度一会儿就上去了,与nginx相差无几(WEB主要是耗IO,在高并发的时候才能显示出代码优化的好处)。
而这个Nagle算法,在Windows上的效果尤为明显。之前使用GIO中的GSocket,也是如此。
对于初学socket编程的人来讲,可能会忘记这里还有个“陷阱”。Nagle算法适用于小包、高延迟的场合,而对于要求交互速度的b/s或c/s就不合适了。socket在建立的时候,默认都是使用Nagle算法的,这会致使交互速度严重降低,因此须要setsockopt函数来设置TCP_NODELAY为1.
不过取消了Nagle算法,就会致使TCP碎片增多,效率可能会下降。因此,这也是要有所取舍的。并发