![EC2/Nginx/Passenger 上的 RMagick 性能非常糟糕](https://linux22.com/image/555609/EC2%2FNginx%2FPassenger%20%E4%B8%8A%E7%9A%84%20RMagick%20%E6%80%A7%E8%83%BD%E9%9D%9E%E5%B8%B8%E7%B3%9F%E7%B3%95.png)
我有一个小型 RoR 应用程序,它使用 RMagick 生成图像,但性能远没有达到我的预期。服务器配置是 EC2 上的 64 位 Ubuntu 11.04 图像,运行 Rails 3.1RC4 / Ruby 1.9.2 / Nginx / Passenger。我尝试了几种不同的 Amazon 实例类型,从小型(使用 32 位图像)到 c1.xlarge,结果非常相似。
启动 ApacheBench (ab -n 10 -c 1) 可获得可接受的平均响应时间为 300 毫秒,测试在大约 2 秒内完成,但将其增加到 5 个并发请求甚至 2 个并发请求会使性能下降到 1500 毫秒,测试需要更长时间。即使在大型实例类型上,ab 运行 (ab -n 10 -c 10) 也会使系统速度降低到 5000 毫秒。我预计响应时间会保持基本一致,但总时间会下降。这是一个错误的假设吗?在每次测试中,内存都不会增加太多(< 1GB),但 CPU 会 100% 地工作。我的 MacBook Pro 运行开发模式可以匹配这些数字。
似乎有些东西是单线程的。该应用程序几乎尽可能简单,唯一复杂的地方是 RMagick 调用。RMagick 是否导致线程问题?是否有更好的 RoR 应用服务器来处理此类问题(Unicorn、Mongrel 集群等)?我是否错误地使用了 ApacheBench?
更新
我在配置中添加了一些新的纯文本路由,它们表现非常好。返回 32K 纯文本几乎不会给 CPU 带来任何问题,我可以达到 72 个请求/秒(这可能是受我的互联网连接限制,而不是 EC2 服务器)。返回 5 个字节可以让我达到超过 250 个请求/秒。
答案1
可能性有很多……事实上,明显缺乏并发性可能表明缺乏适当的 Passenger 配置(passenger_max_pool_size
是关键变量),但如果混合使用 rmagick,问题可能出在磁盘 I/O 上(EBS 卷的性能非常糟糕且不稳定)。另一方面,系统统计数据显示 CPU 已达到最大值这一事实表明 rmagick 正在疯狂消耗 CPU(执行什么?),或者代码中存在其他效率低下的问题,导致 CPU 受限(不过,如果您能够在 c1.xlarge 上实现这一点,我会感到很佩服)。
增加乘客池的规模并收集更好的每个流程和系统范围的统计数据以了解实际情况,答案就会显现出来。
答案2
我们刚刚在 EC2 上调试了 Rails 3 + Nginx + Passenger + PostgreSQL 堆栈性能问题的原因微实例。它们会执行称为 CPU 节流的操作,此博客文章对此进行了很好的解释:http://gregsramblings.com/2011/02/07/amazon-ec2-micro-instance-cpu-steal/
我们进行了一系列 ab 压力测试,并没有发现瓶颈,但整个系统都在变慢。就在那时,我们看到 CPU 占用率达到 100%。
解决方案是更改为小型实例类型,它似乎不会进行限制,或者尝试其他托管服务,例如 Rackspace。
答案3
这个谜题的答案是重新编译 ImageMagick 并关闭 OpenMP。显然,所有线程都在争夺控制权,进程切换完全损害了性能。重新编译后,单个 ECU 可以处理的请求比打开 OpenMP 的 16 个 ECU 还要多。太神奇了!