由于 Facebook 上的病毒式增长,我曾开发过几个经历过高负载的 Rails 应用程序。
您的杂种数量应基于几个因素。如果您的杂种进行 API 调用或发送电子邮件并且必须等待响应,那么您应该尽可能多地运行。否则,请尝试为每个 CPU 内核保持一个杂种,可能还剩下几个。
确保您的服务器使用的是公平代理平衡器(不是循环)。这是执行此操作的 nginx 模块:http: //github.com/gnosek/nginx-upstream-fair/tree/master
这里还有一些关于改进和基准测试应用程序性能以处理负载的其他技巧:
活动记录
Rails 应用程序面临的最常见问题是 ActiveRecord 对象的使用不当。当只需要一个查询时,进行 100 个查询是很容易的。确定这是否可能是您的应用程序问题的最简单方法是设置New Relic。在向您网站上的每个主要页面发出请求后,请查看 newrelic SQL 概述。如果您依次看到大量非常相似的查询(从 id = 1 的帖子中选择 *,从 id = 2 的帖子中选择 *,从帖子中选择 *...),这可能表明您需要使用:包括在您的一个 ActiveRecord 调用中。
其他一些基本的 ActiveRecord 技巧(这些只是我能想到的):
如果您还没有这样做,请确保正确使用数据库表上的索引。
避免在视图中进行数据库调用,尤其是局部调用,很容易忘记您在视图中进行了多少数据库查询。将所有查询和计算推送到您的模型或控制器中。
避免在迭代器中进行查询。通常这可以通过使用 :include 来完成。
尽可能避免让 rails 为大型数据集构建 ActiveRecord 对象。当你调用 Post.find(:all).size 时,会为数据库中的每个 Post 实例化一个新类(它也可能是一个大查询)。在这种情况下,您可能希望使用 Post.count(:all),它会进行一次快速查询并返回一个整数而不实例化任何对象。
User..has_many :objects
像create auser.objects
和user.object_ids
method这样的关联。后者跳过 ActiveRecord 对象的实例化并且可以更快。尤其是在处理大量对象时,这是加快处理速度的好方法。
尽可能学习和使用 named_scope。它将帮助您保持代码很小,并使高效查询变得更加容易。
外部 API 和 ActionMailer
尽可能不要在处理请求时对外部服务进行 API 调用。您的服务器将停止执行代码,直到收到响应。这不仅会增加加载时间,而且您的 mongrel 将无法处理新请求。
如果您绝对必须在请求期间进行外部调用,则需要运行尽可能多的 mongrel,因为您可能会遇到其中许多都在等待 API 响应而不做任何其他事情的情况。(这是构建 Facebook 应用程序时非常常见的问题)
在某些情况下,这同样适用于发送电子邮件。如果您希望许多用户在短时间内注册,请务必对 ActionMailer 传递消息所需的时间进行基准测试。如果它几乎不是即时的,那么您应该考虑将电子邮件存储在您的数据库中,并使用单独的脚本来传递它们。
已经创建了诸如BackgroundRB之类的工具来解决这个问题。
缓存
这是关于在 rails 中缓存的不同方法的一个很好的指南。
基准测试(定位性能问题)
如果您怀疑某个方法可能运行缓慢,请尝试在控制台中对其进行基准测试。这是一个例子:
>> Benchmark.measure { User.find(4).pending_invitations }
=> #<Benchmark::Tms:0x77934b4 @cutime=0.0, @label="", @total=0.0, @stime=0.0, @real=0.00199985504150391, @utime=0.0, @cstime=0.0>
跟踪应用程序中运行缓慢的方法。这些是您要避免频繁执行的那些。在某些情况下,只有第一次调用会很慢,因为 Rails 有查询缓存。您也可以使用Memoization自己缓存该方法。
NewRelic 还将很好地概述方法和 SQL 调用执行所需的时间。
祝你好运!