可能重复:
如何对网站进行负载测试和容量规划
嘿伙计们,我对我的 RoR 应用程序的可扩展性有疑问。
过去几天,我们一直在优化我们的应用程序,在运行 blitz.io 后,我们发现我们的应用程序在 30 秒内大约 1000 次点击后就会超时,我们遇到了大量超时问题。在 1 分钟的测试中,显然有 74% 的用户会超时。
看看我的网站的性能:http://blitz.io/report/1c8eb2f395a5eadeabd62fd831ada9e5
并不是说我们的网站现在会以任何方式遇到这种情况,但我希望设计基础设施来处理这种情况。
在这种情况下通常会做什么?目前我们有一台 Web 服务器和一台数据库服务器。负载平衡是可行的方法吗?
答案1
有很多不同的方法可以提高应用程序的性能。您已经在做一件事,那就是优化。特别是如果您开始优化查询(即修复 n+1 个查询)。我还会研究其他 3 个领域。垂直扩展和水平扩展(http://en.wikipedia.org/wiki/Scalability#Scale_horizontally_vs._vertically) 和解释器。
我喜欢先水平扩展,至少是一点点。拥有 2 个应用服务器和一个负载均衡器将增加您可以处理的请求数量,我最初喜欢这种方法,因为一个应用服务器是单点故障。尽管在这种情况下,负载均衡器成为单点故障。您可以运行 2 个 LB 来实现冗余,但这有点超出您的问题范围。
之后,我会垂直扩展。如果您正在运行像 AWS EC2 实例这样的虚拟机,这就像从 m1.small 移动到 c1.medium 一样简单。许多其他云提供商都有不同的方法来升级到更大的服务器。如果您在自己的硬件上运行,请对您的应用程序进行基准测试,看看瓶颈在哪里(无论如何您都应该这样做,并且首先这样做)。如果瓶颈是内存,只需升级服务器上的内存并重新测试。然后您可能会发现下一个瓶颈是 CPU,因此您需要升级它。
您应该考虑的另一个方面是您使用的 Ruby 解释器。如果您使用的是 MRI(默认的 Ruby 解释器),那么您将牺牲很多性能。MRI 非常适合开发,但在流量很大的站点中,如果可以避免,我不会使用它。MRI 使用全局解释器锁 (GIL),这基本上使您的应用程序成为单线程的。我可能错了,但根据我的理解,每个进程都需要在内存中拥有自己的应用程序副本。因此,如果您有 8 个工作程序处理请求,您的应用程序将占用 8 倍的内存。
还有其他几种 Ruby 解释器,如 JRuby 和 Rubinius。我对 Rubinius 了解不多,但据我所知,它取消了 GIL,从性能角度来看是 MRI 的绝佳替代品。
不过,我非常喜欢 JRuby。如果您还没猜到,JRuby 是一个用 Java 和 Ruby 编写的 Ruby 解释器。它非常稳定,并且利用了 JVM,因此您可以获得本机并发性。如果您选择使用 Java 7,invokedynamic 可以在 JVM 预热后内联方法调用,并像本机 Java 代码一样提高 JVM 语言的性能。使用 JRuby,它不需要为每个进程在内存中创建一个新的应用程序副本,而是使用在内存中共享应用程序单个副本的线程。
如果您决定使用 JRuby,请考虑 Torquebox,这是一个基于 JBoss 构建的出色应用服务器。JRuby 的首席开发人员最近被 Red Hat 聘用,而 Red Hat 已经聘用了 JBoss 和 Torquebox 的开发人员,因此我认为这三个团队之间会有很多交流。
通用基准测试实际上毫无用处,但我所见所闻的所有实际生产应用程序基准测试都比较了 MRI 与 JRuby,性能提升幅度令人难以置信。我不知道您是否会从 Rubinius 获得同样的收益,但迁移到 Rubinius 可能比 JRuby 更容易。