Nginx 教程 #2:性能 已翻译 100%

oschina 投递于 2018/01/22 15:06 (共 19 段, 翻译完成于 01-26)
阅读 6407
收藏 131
6
加载中

大家好,分享即关爱,我们很乐意和你分享一些新的知识,我们准备了一个 Nginx 的教程,分为三个系列,如果你对 Nginx 有所耳闻,或者想增进 Nginx 方面的经验和理解,那么恭喜你来对地方了。

我们会告诉你 Nginx 如何工作及其背后的理念,还有如何优化以加快应用的性能,如何安装启动和保持运行。

这个教程有三个部分:

  • 基本概念 —— 这部分需要去了解 Nginx 的一些指令和使用场景,继承模型,以及 Nginx 如何选择 server 块,location 的顺序。

  • 性能 —— 介绍改善 Nginx 速度的方法和技巧,我们会在这里谈及 gzip 压缩,缓存,buffer 和超时。

  • SSL 安装 —— 如何配置服务器使用 HTTPS

创建这个系列,我们希望,一是作为参考书,可以通过快速查找到相关问题(比如 gzip 压缩,SSL 等)的解决方式,也可以直接通读全文。为了获得更好的学习效果,我们建议你在本机安装 Nginx 并且尝试进行实践。

tcp_nodelaytcp_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

与此同时,诞生了另一个理论,延时 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

正如你可能在一开始就注意到的那样 —— 这可能会导致在持久连接上的一些暂时的死锁。让我们重现它!

假设:

  • 初始拥塞窗口等于 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 包

Tocy
翻译于 2018/01/24 09:47
0

在这个数据交换过程中,由于 Nagel 和延迟 ACK 之间的死锁,引入了 200ms 的延迟。

Nagle 算法是当时真正的救世主,而且目前仍然具有极大的价值。但在大多数情况下,我们不会在我们的网站上使用它,因此可以通过添加 TCP_NODELAY 标志来安全地关闭它。

tcp_nodelay on;     # sets TCP_NODELAY flag, used on keep-alive connections

享受这200ms提速吧!

更多的细节,推荐阅读其他优秀的文章

Tocy
翻译于 2018/01/23 09:31
0

sendfile

正常来说,当要发送一个文件时需要下面的步骤:

  • malloc(3) - 分配一个本地缓冲区,储存对象数据。

  • read(2) - 检索和复制对象到本地缓冲区。

  • write(2) - 从本地缓冲区复制对象到 socket 缓冲区。

这涉及到两个上下文切换(读,写),并使相同对象的第二个副本成为不必要的。正如你所看到的,这不是最佳的方式。值得庆幸的是还有另一个系统调用,提升了发送文件(的效率),它被称为:sendfile(2)(想不到吧!居然是这名字)。这个调用在文件 cache 中检索一个对象,并传递指针(不需要复制整个对象),直接传递到 socket 描述符,Netflix 表示,使用 sendfile(2) 将网络吞吐量从 6Gbps 提高到了 30Gbps

然而,sendfile(2) 有一些注意事项:

  • 不可用于 UNIX sockets(例如:当通过你的上游服务器发送静态文件时)

  • 能否执行不同的操作,取决于操作系统(这里查看更多

在 nginx 中打开它

sendfile on;
Tot_ziens
翻译于 2018/01/24 10:24
0

tcp_nopush

tcp_nopush 与 tcp_nodelay 相反。不是为了尽可能快地推送数据包,它的目标是一次性优化数据的发送量。

在发送给客户端之前,它将强制等待包达到最大长度(MSS)。而且这个指令只有在 sendfile 开启时才起作用。

sendfile on;
tcp_nopush on;

看起来 tcp_nopush 和 tcp_nodelay 是互斥的。但是,如果所有 3 个指令都开启了,nginx 会:

  • 确保数据包在发送给客户之前是已满的

  • 对于最后一个数据包,tcp_nopush 将被删除 —— 允许 TCP 立即发送,没有 200ms 的延迟

Tocy
翻译于 2018/01/23 09:34
0

我应该使用多少进程?

工作进程

worker_process 指令会指定:应该运行多少个 worker。默认情况下,此值设置为 1。最安全的设置是通过传递 auto 选项来使用核心数量。

但由于 Nginx 的架构,其处理请求的速度非常快 - 我们可能一次不会使用超过 2-4 个进程(除非你正在托管 Facebook 或在 nginx 内部执行一些 CPU 密集型的任务)。

worker_process auto;

Tocy
翻译于 2018/01/23 09:37
0

worker 连接

与 worker_process 直接绑定的指令是 worker_connections。它指定一个工作进程可以一次打开多少个连接。这个数目包括所有连接(例如与代理服务器的连接),而不仅仅是与客户端的连接。此外,值得记住的是,一个客户端可以打开多个连接,同时获取其他资源。

worker_connections 1024;

Tocy
翻译于 2018/01/23 09:40
0

打开文件数目限制

在基于 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.

Tocy
翻译于 2018/01/24 09:34
0
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
加载中

评论(3)

局

引用来自“bj我心飞翔”的评论

小编,第三篇关于ssl那篇文章呢
Nginx 教程 #3:SSL 设置 https://www.oschina.net/translate/nginx-tutorial-ssl-setup
bj我心飞翔
bj我心飞翔
小编,第三篇关于ssl那篇文章呢
局
Nginx 系列实用教程 #1:基本概念 https://www.oschina.net/translate/nginx-tutorial-basics-concepts
返回顶部
顶部