Caddy 与 Nginx的基准性能比较 - tjll


这篇博文是关于将 Caddy 与 Nginx 及其各自的性能指标作为反向代理进行基准测试的。

出于某种原因,在我的职业生涯中,我花了过多的时间来处理反向代理。Apache、Nginx、traefik、各种kubernetes服务,以及最近的Caddy。我认为说Caddy一直是我的最爱,这并不是一种偶然的偏见:简单、现代、快速,它做了一个现代反向代理应该做的事情,没有太多的麻烦。

然而,有些人(可以理解!)在面对目前的卫冕冠军Nginx和相对较新的Caddy之间的选择时犹豫不决。Nginx已经存在了很长时间,在它所做的事情上非常出色。Caddy是新来的,它做了一些取舍,不管是好是坏--C语言和Golang语言只是一个例子,必然会导致某种性能上的差异。

设计
我们今天只测试Caddy和Nginx,但我将沿着许多不同的轴线进行切割,以尽可能准确地了解它们各自的性能概况。

我将进行的测试将集中在三个方面。

  • 纯粹的代理内 "合成 "响应。我称它们为 "合成",因为代理只在自己的配置中形成响应代码和主体:在处理响应时,它不从磁盘检索任何资产,也不与后端监听服务交谈。这就把响应请求的所有责任隔离给了反向代理本身,而没有其他依赖资源。
  • 提供文件。反向代理一直在提供预编译的静态资产,所以这是一个重要的用例来衡量。它没有合成测试那么纯粹,因为我们现在涉及到磁盘I/O,但请记住,反向代理也可以依靠缓存。
  • 反向代理。这是一个反向代理的面包和黄油(希望这是显而易见的):与一个服务的后端监听服务聊天。虽然这对测量来说超级重要,但做起来却很棘手,因为现在你引入了一个完全独立的过程,可能会影响响应时间。在实践中,你的后端几乎总是你的瓶颈,因为反向代理的工作只是传递流量。在这方面,我不太喜欢这个测试,因为后端目标的性能最终会渗入到数据中,但我们还是需要这样做(因为 "打开一个新套接字 "的测试路径需要发生)。希望在其他条件相同的情况下,即使绝对值没有严格的代表性,不同的测试运行之间的差异仍将是显著的。

。。。详细点击标题

最后总结
我们学到了什么?

  • 对我来说,最引人注目的新知识是关于失败模式的学习。Nginx会通过拒绝或放弃连接而失败,Caddy会通过减慢一切速度而失败。一个比另一个好吗?对于某些使用情况,几乎是肯定的。有些人想要快速失败,而另一些人则希望不惜一切代价接受连接。关键的一点是,两者是有区别的(坦率地说,我认为我更倾向于故障快速)。
  • 正如预测的那样,"synthetic"响应似乎是最容易的,其次是小的HTML文件内容,其次是反向代理请求,其次是大的HTML内容。Nginx的缓存行为让它在处理静态资产文件时大放异彩(估计还有它的sendfile功能)。
  • Caddy为Go语言的垃圾收集支付了费用,但这并不是一个压迫性的费用(至少在 "正常 "流量水平下)。Nginx几乎毫不费力地使用了大量的内存。Caddy在非破坏性测试中分配的真实内存达到了峰值,这可能是也可能不是很重要,这取决于操作系统可用的总内存量是多少。还有待观察是什么具体的代码路径导致了所有这些malloc/free,但我的测试似乎指向了支撑reverse_proxy的任何机制。
  • Caddy的默认配置是好的。我们把所有的核心都解锁了,我们把所有可以使用的资源都启动了,没有任何内存泄漏。回顾一下,我的 "默认 "和 "优化 "Caddy配置是相同的。默认情况下,Nginx的范围是单一核心(你可以从文档中了解到这一点,但我们现在已经直接针对Caddy观察到这一点)。

在你遇到真正压迫性的流量水平之前,Caddy和优化的Nginx将为你提供良好的服务。我的上述要点都是在边缘情况下需要考虑的,但根据我的观察,这些差异可能很少会出现。

对于 "Caddy或Nginx更好",是否有一个答案?
也许没有,但在这些知识的武装下,也许你可以做出更明智的决定:
在选择反向代理时,除了性能之外,还有其他因素需要考虑。你是否想要Caddy所包含的那些花哨的东西,比如对Let's Encrypt的第一部分支持和一个本地API?你想把你的Nginx知识直接带到支持良好的k8s Nginx ingress控制器上吗?从性能、安全或分析的角度来看,C语言与golang的运行时间对你来说是否重要?

我希望这是个有帮助的练习,并为未来的运营工程师提供有用的数据。