原文作者:Alan Murphy of F5
原文链接:性能调优建议与技巧
转载来源:NGINX 中文官网
NGINX 唯一中文官方社区 ,尽在 nginx.org.cn
Valentin Bartenev 和 Nick Shadrin 等多位 NGINX 团队成员对本文亦有贡献。
在过去的几年里,我曾与一些合作伙伴合作,对他们来说,NGINX Plus 的性能是首要关注的问题。我们的对话往往从难以达到我们发布的性能基准开始。之所以会出现这样的问题,通常是因为他们会直接跳到特定的用例,例如使用现有的 SSL 密钥或针对非常大的文件负载,然后发现 NGINX Plus 的性能低于标准。
从某种程度上来说,这一结果并不意外。我总是向合作伙伴解释说,作为一个软件组件,NGINX Plus 在处理最基本的 HTTP 用例时,能够在任何可用的硬件上以近乎线性的速度运行。不过,想要在特定的用例中达到我们发布的理论性能,NGINX Plus 通常需要在配置、底层操作系统以及硬件设置方面进行一定的调整。
在迄今为止的每一个用例中,我们的合作伙伴只需根据特定的用例场景对操作系统组件和硬件设置进行一定的设置,并调整 NGINX Plus 与这些组件的交互方式,都能在非常独特的用例中让 NGINX Plus 达到理论性能。
经过多年的总结,我整理了这样一份关于如何调整 NGINX 配置、操作系统和硬件的建议与技巧清单,希望能够帮助我们的合作伙伴和客户在特定的用例中提高 NGINX 开源版和 NGINX Plus 的性能。
本文只是对可能影响性能的一部分配置设置提供了指导,并没有涉及 NGINX 性能优化的全部方面,也不一定适合在您的环境中更改下面讨论的每一项设置。
注意: 本博文自首次发布以来已经进行了修订,未来还将进一步审核以确保其尽可能完善。欢迎在下面的评论区中添加您的更改和补充建议,我们将视情况予以采纳。
对于 NGINX 的性能调优问题,我通常建议采用以下工作流程:
值得注意的是,每个部署环境都是独一无二的,并且都有自己的网络和应用性能要求。我们不建议在生产环境中更改一些设置。对于下文所述的配置调整,其效果可能会因为应用类型和网络拓扑的不同而存在明显差异。
鉴于 NGINX 在开源社区中有着强大的基础,多年来许多人都为如何提升性能做出了回馈与贡献。本文视情况添加了一些外部资源的链接,介绍了人们在经过实际生产测试后得出的一些具体的性能调优建议。
请参阅 NGINX 参考文档,详细了解每项设置所允许的的值、默认设置以及设置范围。
本节描述了如何从 OpenSSL 和 NGINX 中删除缓慢且不必要的密码 。
鉴于 SSL 性能如此重要,在环境中尝试不同的密钥长度和类型通常很有必要。这可以帮助您在满足特定安全需求的前提下,在“长密钥、高安全”与“短密钥、高性能”之间找到一个平衡点。有一种简单的测试办法:从更传统的 RSA 密钥转变成椭圆曲线密码算法 (ECC),后者使用更小的密钥长度,因此能够在实现相同的安全级别的情况下拥有更快的计算速度。
要想快速生成自签名的 ECC P-256 密钥进行测试,请运行以下命令:
# openssl ecparam -out ./nginx-ecc-p256.key -name prime256v1 -genkey
# openssl req -new -key ./nginx-ecc-p256.key -out ./nginx-ecc-p256-csr.pem -subj '/CN=localhost'
# openssl req -x509 -nodes -days 30 -key ./nginx-ecc-p256.key -in ./nginx-ecc-p256-csr.pem -out ./nginx-ecc-p256.pem
Gzip 参数可以对 NGINX 提供内容的方式进行细粒度的控制,因此设置不当可能会导致 NGINX 性能下降。启用 gzip 可以节省带宽,改善缓慢连接的页面加载速度。(在本地运行的综合基准测试中,启用 gzip 的效果可能与实际使用效果有所不同。)为了实现最高性能,您可以尝试以下设置:
仅针对相关内容启用 gzip,例如文本、JavaScript 和 CSS 文件;
请勿提高压缩级别,因为这会增加 CPU 资源的消耗,却不能带来与之匹配的吞吐量提升;
针对不同类型和大小的内容启用和禁用 gzip,以评估启用压缩的效果;
有关 gzip 细粒度控制的更多信息,请参考 NGINX gzip 模块的参考文档。
下面介绍几个与连接处理相关的调优选项。关于正确的语法和适用的配置代码块 (http、server、location)等信息,请参阅链接的参考文档。
对于 HTTP 流量,如果您在 upstream 代码块中使用该指令,还必须在配置中添加以下指令,以确保它们在上游服务器组的所有 location 代码块中得到应用(您可以将它们放到各个 location 代码块、父 server 代码块或者 http 级别上):proxy_http_version 1.1 —— NGINX Plus 使用 HTTP/1.1 处理代理的请求 proxy_set_header Connection "" —— NGINX Plus 从代理请求中剥离所有 Connection 请求头
日志是管理和审计系统的一个重要工具。记录大量数据并存储大量日志可能会使系统资源紧张,因此我们建议您仅在非常特别的情况下或在进行性能故障排除时禁用日志记录。
很多开源项目和商用产品厂商都会提供基于 syslog protocol的集中式日志记录系统,此系统可能会给您带来便利。但如果您需要 NGINX 和 NGINX Plus 服务器的指标(整合了最初在日志中记录的信息),您可以使用 NGINX Amplify。
线程池由一个任务队列和处理该队列的多个线程组成。当一个 worker 进程需要执行一个可能很长的操作时,它不会亲自处理这个操作,而是会将这个任务放在线程池的队列中,这样任何空闲线程都可以从中获取和处理。
要启用线程池,请添加 aio threads 指令。请注意,线程池的管理方式可能会受到其他缓冲区相关配置设置的影响。有关调整其他设置以支持线程池的完整信息,请参见我们的博文。
CPU 亲和性 (CPU Affinity) 用于指定 NGINX Plus 为每个 worker 进程使用哪个或哪些 CPU 内核(有关背景信息,请参阅 worker_cpu_affinity 参考文档)。
在大多数情况下,我们建议使用默认的自动参数 worker_processes 指令,它设置了与可用 CPU 内核数量相匹配的 worker 进程的数量。
但是,当 NGINX Plus 在 Docker 等容器环境中运行时,系统管理员可能会选择为容器分配主机上可用的较少的内核资源。在这种情况下,NGINX Plus 会检测主机上可用的内核数量,并在容器实际可用的内核之间轮换 worker 进程。在这种情况下,应该指定 worker_processes 的数值为容器中实际可用的内核数量,以减少 worker 进程的数量。
通常在测试时,我们建议您使用与生产流量相似的流量。但在基础测试中,您可以使用 wrk 等流量生成器,如此处所述。
为 NGINX Plus 快速加载 wrk 会话:
# wrk -t 1 -c 50 -d 20s http://localhost/1k.bin
如有必要,您可以创建一个简单的 1k.bin 文件进行测试:
# dd if=/dev/zero of=1kb.bin bs=1024 count=1
在 CPU 监控模式下执行 top 指令(top 启动后按 1)。
您可以使用不同数量的 worker 进程数量和亲和性绑定设置反复进行测试,来观察是否线性。这是一种有效的方法,可以将访问限制设置为合适的部分可用内核。
这里粗略介绍了一些近似的选型建议,适用于普通 Web 服务和负载均衡,这些值可能不适用于 VOD 流媒体或 CDN 应用场景。
为每 1-2 Gbps 未加密流量分配 1 个 CPU 内核。
小型 (1–2 KB) 响应以及每个连接的 1 个响应会增加 CPU 负载。
为操作系统和其他一般需求分配 1GB RAM。
其余的分配给 NGINX Plus 缓冲区、套接字缓冲区和虚拟内存缓存,粗略估计每个连接需要 1MB。
更多选型建议详情查看NGINX社区官网
磁盘 I/O 受每秒 I/O 操作次数 (IOPS) 所限制。
NGINX Plus 的许多功能都依赖磁盘 I/O 和 IOPS,比如日志和缓存。
NGINX 唯一中文官方社区 ,尽在nginx.org.cn
更多 NGINX 相关的技术干货、互动问答、系列课程、活动资源: 开源社区官网 | 微信公众号