大家好,分享即关爱,我们很乐意和你分享一些新的知识,我们准备了一个 Nginx 的教程,分为三个系列,如果你对 Nginx 有所耳闻,或者想增进 Nginx 方面的经验和理解,那么恭喜你来对地方了。
我们会告诉你 Nginx 如何工作及其背后的理念,还有如何优化以加快应用的性能,如何安装启动和保持运行。
这个教程有三个部分:
基本概念 —— 这部分需要去了解 Nginx 的一些指令和使用场景,继承模型,以及 Nginx 如何选择 server 块,location 的顺序。
性能 —— 介绍改善 Nginx 速度的方法和技巧,我们会在这里谈及 gzip 压缩,缓存,buffer 和超时。
SSL 安装 —— 如何配置服务器使用 HTTPS
创建这个系列,我们希望,一是作为参考书,可以通过快速查找到相关问题(比如 gzip 压缩,SSL 等)的解决方式,也可以直接通读全文。为了获得更好的学习效果,我们建议你在本机安装 Nginx 并且尝试进行实践。
其它翻译版本 (1) 加载中tcp_nodelay
, tcp_nopush
和 sendfile
tcp_nodelay
在 TCP 发展早期,工程师需要面对流量冲突和堵塞的问题,其中涌现了大批的解决方案,其中之一是由 John Nagle 提出的算法。
Nagle 的算法旨在防止通讯被大量的小包淹没。该理论不涉及全尺寸 tcp 包(最大报文长度,简称 MSS)的处理。只针对比 MSS 小的包,只有当接收方成功地将以前的包(ACK)的所有确认发送回来时,这些包才会被发送。在等待期间,发送方可以缓冲更多的数据之后再发送。
if package.size >= MSS.size send(package) elsif acks.all_received? send(package) else # acumulate data end其它翻译版本 (1) 加载中
与此同时,诞生了另一个理论,延时 ACK
在 TCP 通讯中,在发送数据后,需要接收回应包(ACK)来确认数据被成功传达。
延时 ACK 旨在解决线路被大量的 ACK 包拥堵的状况。为了减少 ACK 包的数量,接收者等待需要回传的数据加上 ACK 包回传给发送方,如果没有数据需要回传,必须在至少每 2 个 MSS,或每 200 至 500 毫秒内发送 ACK(以防我们不再收到包)。
if packages.any? send elsif last_ack_send_more_than_2MSS_ago? || 200_ms_timer.finished? send else # wait end其它翻译版本 (1) 加载中
正如你可能在一开始就注意到的那样 —— 这可能会导致在持久连接上的一些暂时的死锁。让我们重现它!
假设:
初始拥塞窗口等于 2。拥塞窗口是另一个 TCP 机制的一部分,称为慢启动。细节现在并不重要,只要记住它限制了一次可以发送多少个包。在第一次往返中,我们可以发送 2 个 MSS 包。在第二次发送中:4 个 MSS 包,第三次发送中:8 个MSS,依此类推。
4 个已缓存的等待发送的数据包:A, B, C, D
A, B, C是 MSS 包
D 是一个小包
场景:
由于是初始的拥塞窗口,发送端被允许传送两个包:A 和 B
接收端在成功获得这两个包之后,发送一个 ACK
发件端发送 C 包。然而,Nagle 却阻止它发送 D 包(包长度太小,等待 C 的ACK)
在接收端,延迟 ACK 使他无法发送 ACK(每隔 2 个包或每隔 200 毫秒发送一次)
在 200ms 之后,接收器发送 C 包的 ACK
发送端收到 ACK 并发送 D 包
在这个数据交换过程中,由于 Nagel 和延迟 ACK 之间的死锁,引入了 200ms 的延迟。
Nagle 算法是当时真正的救世主,而且目前仍然具有极大的价值。但在大多数情况下,我们不会在我们的网站上使用它,因此可以通过添加 TCP_NODELAY 标志来安全地关闭它。
tcp_nodelay on; # sets TCP_NODELAY flag, used on keep-alive connections
享受这200ms提速吧!
更多的细节,推荐阅读其他优秀的文章。
sendfile
正常来说,当要发送一个文件时需要下面的步骤:
malloc(3) - 分配一个本地缓冲区,储存对象数据。
read(2) - 检索和复制对象到本地缓冲区。
write(2) - 从本地缓冲区复制对象到 socket 缓冲区。
这涉及到两个上下文切换(读,写),并使相同对象的第二个副本成为不必要的。正如你所看到的,这不是最佳的方式。值得庆幸的是还有另一个系统调用,提升了发送文件(的效率),它被称为:sendfile(2)
(想不到吧!居然是这名字)。这个调用在文件 cache 中检索一个对象,并传递指针(不需要复制整个对象),直接传递到 socket 描述符,Netflix 表示,使用 sendfile(2) 将网络吞吐量从 6Gbps 提高到了 30Gbps。
然而,sendfile(2) 有一些注意事项:
不可用于 UNIX sockets(例如:当通过你的上游服务器发送静态文件时)
能否执行不同的操作,取决于操作系统(这里查看更多)
在 nginx 中打开它
sendfile on;其它翻译版本 (1) 加载中
tcp_nopush
tcp_nopush 与 tcp_nodelay 相反。不是为了尽可能快地推送数据包,它的目标是一次性优化数据的发送量。
在发送给客户端之前,它将强制等待包达到最大长度(MSS)。而且这个指令只有在 sendfile 开启时才起作用。
sendfile on; tcp_nopush on;
看起来 tcp_nopush 和 tcp_nodelay 是互斥的。但是,如果所有 3 个指令都开启了,nginx 会:
确保数据包在发送给客户之前是已满的
对于最后一个数据包,tcp_nopush 将被删除 —— 允许 TCP 立即发送,没有 200ms 的延迟
worker_process 指令会指定:应该运行多少个 worker。默认情况下,此值设置为 1。最安全的设置是通过传递 auto 选项来使用核心数量。
但由于 Nginx 的架构,其处理请求的速度非常快 - 我们可能一次不会使用超过 2-4 个进程(除非你正在托管 Facebook 或在 nginx 内部执行一些 CPU 密集型的任务)。
worker_process auto;
与 worker_process 直接绑定的指令是 worker_connections。它指定一个工作进程可以一次打开多少个连接。这个数目包括所有连接(例如与代理服务器的连接),而不仅仅是与客户端的连接。此外,值得记住的是,一个客户端可以打开多个连接,同时获取其他资源。
worker_connections 1024;
在基于 Unix 系统中的“一切都是文件”。这意味着文档、目录、管道甚至套接字都是文件。系统对一个进程可以打开多少文件有一个限制。要查看该限制:
ulimit -Sn # soft limit ulimit -Sn # hard limit
这个系统限制必须根据 worker_connections 进行调整。任何传入的连接都会打开至少一个文件(通常是两个连接套接字以及后端连接套接字或磁盘上的静态文件)。所以这个值等于 worker_connections*2 是安全的。幸运的是,Nginx 提供了一个配置选项来增加这个系统的值。要使用这个配置,请添加具有适当数目的 worker_rlimit_nofile 指令并重新加载 nginx。
worker_rlimit_nofile 2048;
worker_process auto; worker_rlimit_nofile 2048; # Changes the limit on the maximum number of open files (RLIMIT_NOFILE) for worker processes. worker_connections 1024; # Sets the maximum number of simultaneous connections that can be opened by a worker process.
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。 2KB翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
2KB项目(www.2kb.com,源码交易平台),提供担保交易、源码交易、虚拟商品、在家创业、在线创业、任务交易、网站设计、软件设计、网络兼职、站长交易、域名交易、链接买卖、网站交易、广告买卖、站长培训、建站美工等服务