如何调整在Heroku上运行的Ruby on Rails应用程序,它使用生产级Heroku Postgres?

时间:2014-03-22 16:28:31

标签: ruby-on-rails postgresql heroku stress-testing

我工作的公司决定将他们的整个堆栈移动到Heroku。它的主要动机是它易于使用:没有sysAdmin,没有哭。但我仍然有一些问题......

我在应用程序平台和Postgres服务上进行了一些负载和压力测试。我使用blitz作为Heroku的插件。我在网站上攻击的用户数在1到250之间。我得到了一些非常有趣的结果,我需要帮助来评估它们。

测试堆栈:

应用程序规范

它没有任何特别的东西。

  • Rails 4.0.4
  • 独角兽
  • database.yml设置连接到Heroku postgres。
  • 不使用缓存。

数据库

它是一个Standard Tengu(Heroku的命名惯例会在一天内杀死我:)正确连接到应用程序。

Heroku配置

我按照{" Deploying Rails Applications With Unicorn"中所说的unicorn.rb应用了所有内容。文章。我有2个常规的网络动态。

WEB_CONCURRENCY  : 2
DB_POOL          : 5

数据

  • episodes表计数100.000~
  • episode_urls表计数300.000~
  • episode_images表计数75.000~

代码

episodes_controller.rb

  def index
    @episodes = Episode.joins(:program).where(programs: {channel_id: 1}).limit(100).includes(:episode_image, :episode_urls)
  end

episodes/index.html.erb

<% @episodes.each do |t| %>
<% if !t.episode_image.blank? %>
<li><%= image_tag(t.episode_image.image(:thumb)) %></li>
<% end %>
<li><%= t.episode_urls.first.mas_path if !t.episode_urls.first.blank?%></li>
<li><%= t.title %></li>
<% end %>

场景#1:

Web dynos   : 2
Duration    : 30 seconds
Timeout     : 8000 ms
Start users : 10
End users   : 10

结果:

HITS 100.00% (484)
ERRORS 0.00% (0)
TIMEOUTS 0.00% (0)
  

这次冲刺在30.00秒内成功击中218次,我们   将6.04 MB的数据传入和传出您的应用。平均命中率   速率为7.27 /秒,相当于每天约627,840次点击。

场景#2:

Web dynos   : 2
Duration    : 30 seconds
Timeout     : 8000 ms
Start users : 20
End users   : 20

结果:

HITS 100.00% (484)
ERRORS 0.00% (0)
TIMEOUTS 0.00% (0)
  

这次冲刺在30.00秒内产生了365次成功命中,我们   将10.12 MB的数据传入和传出您的应用。平均命中率   12.17 /秒的速率转换为大约1,051,200次点击/天。该   平均响应时间为622毫秒。

场景#3:

Web dynos   : 2
Duration    : 30 seconds
Timeout     : 8000 ms
Start users : 50
End users   : 50

结果:

HITS 100.00% (484)
ERRORS 0.00% (0)
TIMEOUTS 0.00% (0)
  

这次冲刺在30.00秒内成功击中371次,我们   将10.29 MB的数据传入和传出您的应用。平均命中率   12.37 /秒的速率转换为约1,068,480次点击/天。该   平均响应时间为2,631毫秒。

场景#4:

Web dynos   : 4
Duration    : 30 seconds
Timeout     : 8000 ms
Start users : 50
End users   : 50

结果:

HITS 100.00% (484)
ERRORS 0.00% (0)
TIMEOUTS 0.00% (0)
  

这次冲刺在30.00秒内产生了484次成功命中,我们   将13.43 MB的数据传入和传出您的应用。平均命中率   16.13 /秒的速率转换为约1,393,920次点击/天。该   平均响应时间为1,856毫秒。

场景#5:

Web dynos   : 4
Duration    : 30 seconds
Timeout     : 8000 ms
Start users : 150
End users   : 150

结果:

HITS 71.22% (386)
ERRORS 0.00% (0)
TIMEOUTS 28.78% (156)
  

这次冲刺在30.00秒内成功击中了386次,我们   将10.76 MB的数据传入和传出您的应用。平均命中率   12.87 /秒的速率转换为大约1,111,680次点击/天。该   平均响应时间为5,446毫秒。

场景#6:

Web dynos   : 10
Duration    : 30 seconds
Timeout     : 8000 ms
Start users : 150
End users   : 150

结果:

HITS 73.79% (428)
ERRORS 0.17% (1)
TIMEOUTS 26.03% (151)
  

这次冲刺在30.00秒内产生了428次成功命中,我们   将11.92 MB的数据传入和传出您的应用。平均命中率   14.27 /秒的速率转换为约1,232,640次点击/天。该   平均响应时间为4,793毫秒。你有更大的问题,   但是:在这次抢购期间,26.21%的用户遇到了超时或   错误!

总摘要:

  • &#34;命中率&#34;即使有150个用户向应用程序发送请求,也永远不会超过15个。
  • 越来越多的网络dynos无助于处理请求。

的问题:

  1. 当我使用缓存和memcached(来自Heroku的Memcachier插件)时,即使是2个web dynos也可以处理&gt;每秒180次点击。我只是试图理解dynos和postgres服务可以在没有缓存的情况下做什么。通过这种方式,我试图了解如何调整它们。怎么做?

  2. 标准Tengu据说有200个并发连接。那为什么它永远不会达到这个数字呢?

  3. 如果拥有prdouction level db和增加web dynos不会有助于扩展我的应用程序,那么使用Heroku是什么意思?

  4. 可能是最重要的问题:我做错了什么? :)

  5. 感谢您阅读这个疯狂的问题!

1 个答案:

答案 0 :(得分:1)

我特别想出了这个问题。

首先,请记住视图中的代码:

<% @episodes.each do |t| %>
<% if !t.episode_image.blank? %>
<li><%= image_tag(t.episode_image.image(:thumb)) %></li>
<% end %>
<li><%= t.episode_urls.first.mas_path if !t.episode_urls.first.blank?%></li>
<li><%= t.title %></li>
<% end %>

这里我在迭代中收到每集episode_image。即使我在我的控制器中使用includes,我的表架构也出现了一个很大的错误。 我的episode_id表格中没有episode_images的索引!。这导致了极高的查询时间。我发现它使用New Relic的数据库报告。所有其他查询时间均为0.5毫秒或2-3毫秒,但episode.episode_image导致差不多6500毫秒!

我不太了解查询时间和应用程序执行之间的关系,但是当我在我的episode_images表中添加索引时,现在我可以清楚地看到差异。如果您的数据库架构正确,那么通过Heroku进行扩展可能不会遇到任何问题。但是任何dyno都无法帮助你设计一个设计糟糕的数据库。

对于可能遇到同样问题的人,我想告诉你一些关于Heroku web dynos,Unicorn worker和Postgresql活动连接之间关系的调查结果:

基本上,Heroku为您提供了一个dyno,它是一种具有1个核心和512MB RAM的小型虚拟机。在这个小虚拟机内,你的Unicorn服务器运行。 Unicorn有一个主进程和工作进程。您的每个Unicorn工作人员都有自己与现有Postgresql服务器的永久连接(不要忘记查看this)这基本上意味着当你有一个Heroku dyno与3个Unicorn工作者在其上运行时,你有至少4个活动连接。如果您有2个网络动态,则至少有8个活动连接。

假设您有一个标准T​​engu Postgres,其中包含200个并发连接限制。如果你有错误的数据库设计有问题的查询,数据库也不能更多dynos可以在没有缓存的情况下保存你...如果你有长时间运行的查询,除了缓存之外别无选择,我认为。

以上都是我自己的发现,如果有任何问题请通过你的评论警告我。