1

在接下来的几天里,我们很有可能会受到技术压力的影响。不幸的是,我们还没有上线,所以我们无法很好地估计我们的系统如何处理生产观众。

我们的生产设置由 2 个 EngineYard 切片组成,每个切片带有 3 个 mongrel 实例,使用 Postgres 作为数据库服务器。

显然,我们的应用程序将如何保持的很大一部分与我们的实际代码和查询等有关。但是,如果有任何关于期望什么样的负载或有经验的人的经验的提示/指针,那将是很好的。经历过。6 个 mongrel 实例(如果服务器可以接受的话,可能是 8 个)听起来会处理负载,或者至少是大部分?

4

6 回答 6

3

由于 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 技巧(这些只是我能想到的):

  1. 如果您还没有这样做,请确保正确使用数据库表上的索引。

  2. 避免在视图中进行数据库调用,尤其是局部调用,很容易忘记您在视图中进行了多少数据库查询。将所有查询和计算推送到您的模型或控制器中。

  3. 避免在迭代器中进行查询。通常这可以通过使用 :include 来完成。

  4. 尽可能避免让 rails 为大型数据集构建 ActiveRecord 对象。当你调用 Post.find(:all).size 时,会为数据库中的每个 Post 实例化一个新类(它也可能是一个大查询)。在这种情况下,您可能希望使用 Post.count(:all),它会进行一次快速查询并返回一个整数而不实例化任何对象。

  5. User..has_many :objects像create auser.objectsuser.object_idsmethod这样的关联。后者跳过 ActiveRecord 对象的实例化并且可以更快。尤其是在处理大量对象时,这是加快处理速度的好方法。

  6. 尽可能学习和使用 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 调用执行所需的时间。

祝你好运!

于 2009-03-31T02:21:44.587 回答
1

查看一些负载测试软件,例如WEBLoad,或者如果您有钱,可以使用 Quick Test Pro。这将有助于给你一些想法。WEBLoad 可能是在您的情况下最好的测试。

您可以生成数以千计的虚拟节点访问您的站点,并且可以根据该负载检查服务器的性能。

于 2009-03-23T05:06:36.580 回答
0

根据我观察我们的一些客户吸收嘎吱嘎吱声的经验,流量相当适中 - 不是人们似乎期望的骨头粉碎峰值。现在,如果你被联合并在雅虎的页面上制作,事情可能会有所不同。

如果您想了解他们如何处理它(Yahoo FP),请搜索 Facestat.com 的经验。

如果您的服务器太热,我的建议是准备关闭注册或转到更静态的网站版本。使用监控/分析工具也是一个好主意,我喜欢 FiveRuns Manage 工具以便于设置。

于 2009-03-23T14:14:31.117 回答
0

由于您使用的是 EngineYard,因此您应该能够在必要时分配更多机器来处理负载

于 2009-03-23T18:54:30.397 回答
0

您的大问题可能不是传入请求的数量,而是数据库中的数据量向您显示您的查询没有使用您期望的索引,或者返回太多数据,例如用户列表页面有效有 10 个用户,但是当您尝试在该页面上显示 10,000 个用户时死掉,因为您没有添加分页(will_paginate 插件几乎是您的朋友 - 注意为您生成的“选择计数(*)”查询)

所以要注意两件事:

  1. 缺少索引
  2. 每页数据过多

对于#1,有一个插件在每次查询后运行“解释...”查询,因此您可以手动检查索引使用情况

有一个插件可以为您生成各种类型的数据,也可以帮助您填充数据库以测试这些查询。

对于 #2,使用 will_paginate 插件或其他方式来减少每页的数据。

于 2009-03-25T20:52:22.547 回答
0

我们的设置与您基本相同,在 EY 有 2 个 prod slice 和一个 staging slice。我们发现 ab 是一个很棒的负载测试工具 - 只需编写一个 bash 脚本,其中包含您希望被命中的 url 并将其指向您的切片。观看 NewRelic 统计数据,它应该让您了解您的应用程序可以处理的负载以及您可能需要优化的地方。

我们还发现 query_reviewer 也非常有用。它非常适合查找那些未索引的表和 n+1 查询。

于 2009-03-31T00:31:57.173 回答