生产环境下的Rails性能调优?

21

我即将部署一个基于Rails 3.1.x构建的应用程序,并开始运行一些性能测试。经过一番使用ab后,我看到了一些非常令人沮丧的结果,在Heroku上每秒只能处理约15个请求。

在本地测试时,我看到了类似的结果,这真正证明了这是一个应用问题而不是其他问题。

我正在使用Unicorn,它比Celadon Cedar上的Thin快约40%。此外,我正在使用PGSQL共享数据库。

我希望有人可以分享一个清单或者说是启动清单,以便我为生产环境做好准备并提高应用程序的速度调优。到目前为止,我没有找到一个真正简明可行的清单来解决我的问题。

或者如果您在处理此类问题时有实际的经验,请给予任何建议!

4个回答

19

我在Heroku上调试应用程序花费了一些时间,并在各种环境中对Rails应用程序进行了性能调优。

当我运行ab -n 300 -c 75 ...myapp.com....命令时,我的主站点已有备份,该站点位于免费的cedar计划下,并使用unicorn。

Requests per second:    132.11 [#/sec] (mean)
Time per request:       567.707 [ms] (mean)
Time per request:       7.569 [ms] (mean, across all concurrent requests)

(这只是以一个简单的页面为例,来演示Heroku在免费方案上有多快。并不是说“你的应用程序应该这么快”)

以下是我的Rails性能调优101清单:

  1. 首先测量浏览器/页面加载时间(浏览器会发出许多请求,ab仅向您报告其中一个请求,而通常您的主页请求不是问题所在),从像www.webpagetest.orgwww.gtmetrix.com这样的工具中获取公共页面的基准页面加载数据,或从Yslow、Google Page Speed或Dynatrace等浏览器工具中获取私有页面的数据。如果您查看页面加载瀑布图(在Chrome/Firefox中的“Net”面板中),它通常显示您的HTML加载很快(在一秒内),但其他所有内容需要1-3秒才能加载完成。遵循Yslow/PageSpeed建议进行改进(确保您充分利用了Rails 3.1资源管道功能)。

  2. 通过日志文件或New Relic找到“最慢/最频繁访问”的请求的最佳位置,并对该请求进行分析(Ruby速度缓慢/内存使用过多还是查询过多?)。您需要可靠的方法来检测和监视性能问题,而不是随意更改。一旦您确定了一些目标领域,请创建测试脚本以帮助进行前/后测试,证明您的更改有所帮助,并检测回归是否发生。

  3. 缺少数据库列索引是最常见的问题之一,也是最容易解决的问题之一。在目标查询上运行explain,或查看慢查询日志,以查看查询规划器正在执行什么操作。根据需要添加外键、搜索列或主数据(覆盖索引)的索引。使用实际生产数据重新测试以证明它确实有所改善(您可以在Heroku上运行explain,以及运行查询以查找缺失或未使用的索引)。

  4. 大多数性能不佳的Rails应用程序都会遭受N+1查询的困扰,因为太容易编写order.owner.address.city等代码,而不考虑它在循环中的运行情况。N+1查询并不一定是慢查询,因此它们不会出现在慢查询日志中,只是数量很多,一次性处理更有效率。使用:include或.includes()来进行数据的贪婪加载,或者考虑以其他方式进行查询。

  5. 分析您的应用程序流程,寻找缓存机会。如果用户在索引页面和详细信息页面之间来回跳转,并且再次返回索引页面,也许可以通过ajax视图,而不是离开索引页面来更快地为他们提供所需的数据。在我的博客上,我写了一些关于这个问题的更多想法

我在今年的WindyCityRails大会上发表了有关这些技术和其他想法的演讲。您可以在我的www.RailsPerformance.com博客上观看视频

我喜欢Heroku的原因在于您必


你好,请问您能帮我查看一下与此类似的问题吗?链接为http://stackoverflow.com/questions/22580297/how-to-tune-a-production-level-heroku-postgres-with-a-ruby-on-rails-application。谢谢。 - scaryguy

6

有一些非常容易实现的优化方法,通常可以带来显著的性能提升:

  1. 通过使用更高效的 ActiveRecord 语句来减少数据库查询次数。确保在适当的情况下使用 includejoin,并尽可能使用 empty? 而不是 any? 来避免在只需要 COUNT 时出现 SELECT
  2. 特别是在较重的页面上,即使只缓存几分钟,也要缓存视图。您还可以将较大或动态的部分拆分为可缓存的局部视图,而不会产生任何负面影响。
  3. 将所有网络活动移至后台作业。这包括发送电子邮件、从其他网站获取页面和进行 API 调用(甚至 [尤其?] 到 Heroku)。Ruby 中有很多非常好的后台作业处理库,DelayedJob 非常受欢迎,因为它适用于任何 ActiveRecord 数据库,但我最喜欢的是 Resque。

请注意不要花太多时间优化Ruby例程。除非您正在处理大量数据或处理(例如图像调整大小),否则优化循环或最小化内存使用可能不会带来非常显着的收益。如果您发现某些页面存在问题,请深入挖掘日志,了解这些请求期间发生了什么。

如果您还没有这样做,像HireFireApp这样的自动缩放应用程序非常适合让您通过横向扩展处理大量请求,而无需在低峰期运行多余的dynos。

PS:有一个名为Blitz的新Heroku Add-On,可以让您测试高达5,000个用户的并发负载。


好东西,感谢您的评论。是的,HireFire很棒,Michael是个很不错的人,我把他视为朋友。我将深入挖掘您的评论,并让您知道我的结果。其中有几个目前不适用,但我很感激“不优化Ruby例程”的建议,因为那是我最初考虑的问题之一,但似乎效果并不理想。 - ylluminate
@coreyward,嗨Corey,你能提供简单的Rails咨询服务吗?我在你的网站上找不到你的联系方式。如果可以的话,请发送电子邮件至info@panabee.com。谢谢! - Crashalot

4
最全面的单一答案是使用类似NewRelic之类的工具来检测您的应用程序并查找慢点。然后,您可以对代码进行优化或缓存以平滑这些慢点。作为Heroku客户,您可以免费安装NewRelic - 这是一个可以从Heroku控制台添加到部署中的插件。

一旦您了解了什么在减速,那么您就可以开始处理它。Heroku处理大多数性能调优的dev-ops端,因此您不需要在那里做任何事情。但是,通过对数据库查询进行优化以及在适当的地方执行片段和操作级缓存,仍然可以获得很大的收益。


谢谢。我略微使用了NewRelic作为免费服务,但现在看来我确实应该考虑其他选项,以便了解哪些地方存在问题。谢谢!我会在这里回复结果的。 - ylluminate

2
由于目前没有出现任何问题,我会为PostgreSQL部分提供答案。我无法协助Ruby。
您可以在PostgreSQL维基上找到优化性能的优秀起点。

由于在Rails应用程序中通常不编写SQL查询,并且(如所述)在Heroku上服务器设置和硬件是无关紧要的,因此您的答案并不是非常准确。 - coreyward
@coreyward:很好。我的回答似乎引起了一些关注,这产生了两个更切题的答案。 - Erwin Brandstetter
1
感谢@ErwinBrandstetter的提醒!确实,关于调整Heroku基于AWS的共享PGSQL数据库,没有太多可以做的,但是根据其他注释,查询可能是瓶颈。 - ylluminate
服务器设置非常出色,我不使用Heroku。 - damuz91

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接