nginx配置sendfile、tcp_nopush、tcp_nodelay
Nginx 配置优化项:
sendfile        on;
tcp_nopush      on;
tcp_nodelay    on;
1、TCP_NODELAY
怎么可以强制socket在它的缓冲区⾥发送数据?
⼀个解决⽅案是 TCP 堆栈的 TCP_NODELAY 选项。这样就可以使缓冲区中的数据⽴即发送出去。
Nginx的 TCP_NODELAY 选项使得在打开⼀个新的 socket 时增加了TCP_NODELAY选项。
但这时会造成⼀种情况:
终端应⽤程序每产⽣⼀次操作就会发送⼀个包,⽽典型情况下⼀个包会拥有⼀个字节的数据以及40个字节长的包头,于是产⽣4000%的过载,很轻易地就能令⽹络发⽣拥塞。
为了避免这种情况,TCP堆栈实现了等待数据 0.2秒钟,因此操作后它不会发送⼀个数据包,⽽是将这段时间内的数据打成⼀个⼤的包。这⼀机制是由Nagle算法保证。
Nagle化后来成了⼀种标准并且⽴即在因特⽹上得以实现。它现在已经成为默认配置了,但有些场合下把这⼀选项关掉也是合乎需要的。现在假设某个应⽤程序发出了⼀个请求,希望发送⼩块数据。我们可以选择⽴即发送数据或者等待产⽣更多的数据然后再⼀次发送两种策略。
如果我们马上发送数据,那么交互性的以及客户/服务器型的应⽤程序将极⼤地受益。如果请求⽴即发出那么响应时间也会快⼀些。以上操作可以通过设置套接字的 TCP_NODELAY = on 选项来完成,这样就禁⽤了Nagle 算法。(不需要等待0.2s)
2、tcp_nopush
在 nginx 中,tcp_nopush 配置和 tcp_nodelay "互斥"。它可以配置⼀次发送数据的包⼤⼩。也就是说,它不是按时间累计  0.2 秒后发送包,⽽是当包累计到⼀定⼤⼩后就发送。在 nginx 中,tcp_nopush 必须和 sendfile 搭配使⽤。
3、sendfile
现在流⾏的web 服务器⾥⾯都提供 sendfile 选项⽤来提⾼服务器性能,那到底 sendfile是什么,怎么
影响性能的呢?sendfile实际上是
Linux2.0+以后的推出的⼀个系统调⽤,web服务器可以通过调整⾃⾝的配置来决定是否利⽤ sendfile这个系统调⽤。先来看⼀下不⽤ sendfile 的传统⽹络传输过程:
read(file,tmp_buf, len);
write(socket,tmp_buf, len);
nginx 配置文件硬盘 >> kernel buffer >> user buffer>> kernel socket buffer >>协议栈
⼀般来说⼀个⽹络应⽤是通过读硬盘数据,然后写数据到socket 来完成⽹络传输的。上⾯2⾏⽤代码解释了这⼀点,不过上⾯2⾏简单的代码掩盖了底层的很多操作。来看看底层是怎么执⾏上⾯2⾏代码的:
1、系统调⽤ read()产⽣⼀个上下⽂切换:从 user mode 切换到 kernel mode,然后 DMA 执⾏拷贝,把⽂件数据从硬盘读到⼀个 kernel buffer ⾥。
2、数据从 kernel buffer拷贝到 user buffer,然后系统调⽤ read() 返回,这时⼜产⽣⼀个上下⽂切换:从kernel mode 切换到 user
mode。
3、系统调⽤write()产⽣⼀个上下⽂切换:从 user mode切换到 kernel mode,然后把步骤2读到 user buffer的数据拷贝到 kernel
buffer(数据第2次拷贝到 kernel buffer),不过这次是个不同的 kernel buffer,这个 buffer和 socket相关联。
4、系统调⽤ write()返回,产⽣⼀个上下⽂切换:从 kernel mode 切换到 user mode(第4次切换了),然后 DMA 从 kernel buffer拷贝数据到协议栈(第4次拷贝了)。
上⾯4个步骤有4次上下⽂切换,有4次拷贝,我们发现如果能减少切换次数和拷贝次数将会有效提升性能。在kernel2.0+ 版本中,系统调⽤sendfile() 就是⽤来简化上⾯步骤提升性能的。sendfile() 不但能减少切换次数⽽且还能减少拷贝次数。
再来看⼀下⽤ sendfile()来进⾏⽹络传输的过程:
sendfile(socket,file, len);
硬盘 >> kernel buffer (快速拷贝到kernelsocket buffer) >>协议栈
1、系统调⽤sendfile()通过 DMA把硬盘数据拷贝到 kernel buffer,然后数据被 kernel直接拷贝到另外⼀个与 socket相关的 kernel buffer。这⾥没有 user mode和 kernel mode之间的切换,在 kernel中直接完成了从⼀个 buffer到另⼀个 buffer的拷贝。
2、DMA 把数据从 kernelbuffer 直接拷贝给协议栈,没有切换,也不需要数据从 user mode 拷贝到 kernel mode,因为数据就在 kernel ⾥。
步骤减少了,切换减少了,拷贝减少了,⾃然性能就提升了。这就是为什么说在Nginx 配置⽂件⾥打开 sendfile on 选项能提⾼ web server性能的原因。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。