性能比拼: Nginx vs Caddy
本内容是对知名性能评测博主 Anton Putra Nginx vs Caddy Performance 内容的翻译与整理, 有适当删减, 相关指标和结论以原作为准
引言
在本期视频中,我们将对比 Nginx 和 Caddy---
一个用 Go 编写的 Web 服务器和反向代理。
在第一个测试中,我们会使用 Nginx 和 Caddy 通过 HTTPS 提供静态网站服务,并在两个服务器上启用默认压缩。我们重点关注的是延迟,使用 p99 百分位进行衡量。吞吐量方面,我们会查看每个 Web 服务器可以处理的请求数。为评估资源饱和度,我们将监控 CPU 与内存相对于整台虚拟机的使用情况,以及网络流量。最后,我们还会测量每个 Web 服务器的错误率或可用性。
在第二个测试中,我们会将 Nginx 和 Caddy 用作反向代理和负载均衡器,将流量分发给后端应用。此外,我们也会统计这些应用的 CPU 和内存使用情况。
我使用 AWS 来运行所有测试,并根据不同的工作负载选择最新的 EC2 实例。例如,在这个视频中,我为 Web 服务器配置了 m7a.large 实例,后端应用使用同样的 EC2 类型。我还设置了一个由 Graviton 实例组成的 EKS 集群,用来运行客户端并生成负载。同时使用 Route 53 创建私有托管区域,用于服务发现。每次基准测试运行数小时,通常每次测试的花费在 20 到 50 美元之间。
测试设计
我使用 Terraform 创建 VPC 及测试所需的所有网络组件。
在第一个测试中,我使用基于 React 的 JavaScript 框架 Next.js 来生成一个简单的网站,并将其编译为 HTML、CSS 和 JavaScript 文件。然后我为每个 Web 服务器创建一个大型 EC2 实例(2 个 CPU 和 8 GB 内存),并将网站上传至每台服务器。同时,我创建了一个自签名的证书颁发机构,并为 Nginx 和 Caddy 签发证书。
为生成负载,我创建一个 EKS 集群,并使用 Kubernetes job 为每台 Web 服务器部署约 20 个 pod。为每个客户端提供证书以认证访问 Web 服务器。这种设置很常见:两个服务器都使用压缩服务静态内容,并通过 HTTPS 提供安全传输。TLS 证书还允许我们从 HTTP/1 升级到更高效的二进制协议 HTTP/2。
在第二个测试中,我为每台服务器配置了两个额外的 EC2 实例,作为后端应用,实例类型与前面相同。此测试中,每台服务器被配置为反向代理和负载均衡器,将流量分发到后端应用。由于负载较小,此测试未启用压缩。每个应用向客户端返回硬编码数据。此外,我配置了代理传递原始客户端 IP 地址,使用的是 X-Forwarded-For
头。
当反向代理接收到来自客户端的请求时,会终止该请求,并以自身 IP 作为源地址,向应用发起新的请求。如果你的应用需要获取客户端的真实 IP,可以使用 X-Forwarded-For
头或配置 proxy protocol。
配置概览
在之前与 Apache 的测试中,我主要使用 Nginx 的默认设置,这些设置已经很高效。但我收到 Melroy 的一个 Pull Request,包含了一些优化建议,于是在这次测试中应用了它们。我还做了一些额外的配置更改,并测试了不同的线程设置。
这些更改对第一个测试影响不大,但在第二个测试中显著提升了 Nginx 作为反向代理和负载均衡器的性能。配置中还包括 multi_accept
设置,并且我提高了系统允许打开的文件数限制。
在网站配置中,我只使用了 443 端口用于 HTTPS,并提供了我本地生成的证书和私钥。第二个测试中,我声明了一个上游服务,并使用默认的轮询算法将流量分发给后端应用。我也添加了 X-Forwarded-For
头,大致就是这些配置。源代码可在我的公共 GitHub 仓库中找到,链接会在视频描述中提供。
在之前的测试中,我使用的是最新稳定版本 1.26.2。这次测试使用的是主线分支的最新版本 1.27.2。
另一方面,我们来看 Caddy。据我所知,Caddy 最大的卖点是简单易用。如果你不想花时间配置 Nginx,可以选择 Caddy,它几乎能完成 Nginx 所能做的一切,但只需最少配置。这个 Web 服务器对初学者也很友好。根据官方文档,一个非常简单的配置就可以用于生产环境。
因此,我在测试中故意使用了默认的“生产”设置。
我为 Caddy 编译并使用了相同的网站,也启用了压缩。我提供了自己的证书和私钥,并使用 file_server
指令来提供网站服务。默认情况下,Caddy 的访问日志非常详细,为了公平比较,我使用了类似 Nginx 和 Apache 的日志格式,以减少文件系统负载。第二个测试中,我同样使用了最小配置,使用 reverse_proxy
设置。
所以从功能上看,这两个服务器都使用压缩和 HTTP/2 协议,并通过 HTTPS 提供服务。Caddy 使用的版本是 2.8.4。
第一个测试:Web 服务器
现在让我们开始第一个测试。对我来说,延迟和吞吐量是最重要的指标,当然还有可用性。
测试开始时,Nginx 在提供静态网站时延迟明显更低。从 CPU 使用率来看,你可以预测哪个 Web 服务器更容易先失败。内存使用方面,两者非常接近,约占 8GB 总内存的 6%。你还会注意到,Nginx 传输的网络数据稍多一些,主要是因为它的压缩级别略低。
在每秒约 4,000 个请求时,Caddy 的 CPU 使用率达到了 50%,从那时开始延迟开始上升。至于每个请求的“有效延迟”标准,需要根据你的使用场景和预期定义。在这个测试中,我使用的是 1 秒超时,超时后返回 408 状态码,这会影响服务的可用性。
当请求达到每秒约 8,000 个时,Caddy 在每秒请求数方面开始落后于 Nginx。此时出现了显著的延迟峰值,我怀疑这可能是 Go 的垃圾回收导致的,但也可能是别的原因。如果你有不同看法,欢迎告诉我。
在每秒约 10,000 个请求时,Caddy 的 CPU 使用率接近 100%,性能进一步下降。
本次测试中,Nginx 和 Caddy 部署在独立的虚拟机上,因此不存在 CPU 限流的问题。现在我们来看看优化后的 Nginx 最多能处理多少请求。虽然花了点时间,但最终 Nginx 达到了接近每秒 22,000 个请求,与之前 Apache 视频中的结果几乎一致,不过这次表现更加稳定。在上次测试中,Nginx 在达到 80% CPU 使用率后立即崩溃,而这次即使达到相同请求数仍能继续运行。
现在我们打开每张图表,查看整个测试持续时间。整个测试持续了大约 2 小时。
首先是每秒请求数图表---
在 8,000 请求/秒时 Caddy 开始性能下降,最高约 10,000 请求/秒;而 Nginx 处理了超过两倍的请求,达到 22,000 请求/秒。
接着是 p99 延迟图表。Caddy 开始性能下降后延迟上升明显,但从测试一开始,Nginx 的延迟就更稳定,显著低于 Caddy。对于面向客户端的应用来说,低延迟能够提供更好的用户体验。
然后是两个 Web 服务器的 CPU 使用情况。Web 服务器是典型的 CPU 密集型应用,因此 CPU 使用率越低,通常意味着更好的响应速度和更高吞吐量。
接下来是内存使用图表。虽然有几次波动,但始终在 6% 到 8% 之间。因此,在这个测试中,内存并不是性能瓶颈。
然后是可用性图表。你可以看到测试后期错误率略有上升,但比例极小---
每秒几千个请求中只有 1~2 个错误。你可能会好奇为什么 Caddy 没有错误?这是因为 Nginx 会尝试处理所有请求,而 Caddy 在过载时会拒绝新请求,因此不会产生超时错误。
最后是网络流量图表。在峰值时,Nginx 的吞吐量接近每秒 600MB,而 Caddy 只有一半不到。
如果你是初学者或 Web 开发者,不想花太多时间优化 Web 服务器,Caddy 是个不错的选择。如果你担心 TLS 证书管理,Caddy 也非常适合。但从性能来看,Nginx 明显更强,可以大幅降低运行成本。我估算使用 Nginx 可节省近一半的基础设施费用。最终选择权在你手中,如果是个人项目或少量用户,Caddy 完全能胜任。
第二个测试:反向代理
我们继续进行第二个测试。在这个测试中,我们将每个服务器作为反向代理和负载均衡器使用。
最初我很高兴看到 Caddy 表现优于 Nginx,但这种优势很快就消失了。当请求达到每秒 900 次,CPU 使用率仅为 12% 时,Caddy 的延迟就开始上升。相比之下,Nginx 的延迟保持平稳。
这个测试中让我最惊讶的是:为什么 Nginx 后端的应用承受了比其他代理更大的负载?之前 Apache 的测试中也出现了类似情况。如果你对此有见解,请告诉我。
这个测试中,Nginx 的内存使用稍高于 Caddy,但对于这种 CPU 密集型应用,内存影响不大。
当请求达到每秒约 10,000 次时,Caddy 出现了与上次类似的延迟问题。我怀疑也是垃圾回收引起的,但欢迎你提供其他想法。
当请求达到每秒 14,000 次时,Caddy 的 CPU 使用率几乎达到 100%,无法处理更多请求,延迟也开始明显上升。接下来我们看看 Nginx 能处理多少请求。
整个测试持续近 3 小时,Nginx 最终达到了近 27,000 请求/秒的吞吐量,比 Apache 测试中的结果还高。可见,如果打算将 Nginx 用作反向代理,务必要进行优化,而不是依赖默认配置。
我们接着查看每个图表:
- 吞吐量:Caddy 最多处理约 14,000 请求/秒,而 Nginx 达到约 27,000 请求/秒。
- 延迟图表:测试初期 Caddy 表现稍好,但很快失去优势。
- CPU 使用情况
- 内存使用情况
- 可用性图表:Caddy 的可用性在某些阶段甚至降至 42%,而 Nginx 几乎保持在 99.99%。
- 网络流量图表
- 反向代理后应用的 CPU 使用情况:Nginx 后的应用 CPU 使用率异常高,请告诉我你对此的看法。
- 反向代理后应用的内存使用情况
结论:我认为 Caddy 是非常适合 Web 开发者或初学者的 Web 服务器。但如果你开始搭建负载均衡和反向代理,说明你已经有一定流量,应开始考虑架构优化并深入学习 Web 服务器和代理。此时,Nginx 提供更高吞吐量和更低延迟,运行成本更低。因此,与其使用 Caddy,不如选择 Nginx 或其他更高效的代理。