了解为什么我的Rails 4应用程序随机超时

时间:2016-03-26 02:22:37

标签: sql ruby-on-rails ruby ruby-on-rails-4 heroku

在过去的几个月里,我的网站(使用Heroku在Rails 4上运行)一直没有问题。流量稳定,响应时间低于500毫秒。

今天随机,响应时间高达20,000毫秒+。

Heroku response times

在查看我的日志时,我注意到ActiveRecord花费了不同的时间来运行SELECT DISTINCT COUNT。事实上,这似乎导致了缓慢的负荷。

(5029.1ms)  SELECT DISTINCT COUNT(DISTINCT "impressions"."session_hash") FROM "impressions" WHERE "impressions"."impressionable_id" = $1 AND "impressions"."impressionable_type" = $2  [["impressionable_id", 826], ["impressionable_type", "Article"]]

我想说这是由印象派宝石和我用于显示文章计数的我的计数器缓存造成的,但我不确定。

我现在也是第一次在我的日志中看到此错误:

PG::DuplicatePstatement: ERROR:  prepared statement "a9" already exists

了解正在发生的事情的任何帮助都会很棒。似乎无法找到有关该问题的文档。非常奇怪,我的应用程序已经稳定运行了几个月,就在今天它决定走下坡路。

我也在使用Heroku的Rack Timeout gem。我听说这个宝石可以直接或间接导致上述错误,但我可以解决为什么会发生这种情况。如果我能提供任何其他信息或指标,请与我们联系。

一天后续更新:

响应时间自行恢复正常(<500毫秒)。无法弄清楚为什么会出现这样的随机峰值。

仅供参考,我的文章展示页面中的此代码正在执行上述SELECT DISTINCT COUNT查询,该页面只是计算会话特有的展示次数:

<%= @article.impressionist_count(filter: :session_hash) %>

1 个答案:

答案 0 :(得分:0)

发生此错误PG::DuplicatePstatement: ERROR: prepared statement "a9" already exists是因为您已启用预准备语句。我不知道这个错误的确切原因是什么。我在测试版本和其他一些地方随机看到它。我一般建议您禁用预准备语句,因为它可以为您节省一些真正的麻烦。当你获得更多流量并尝试扩大你的dynos时,你可以开始看到来自pg gem的内存错误。

要禁用,只需将其添加到您的database.yml

production:
    adapter: postgresql
    prepared_statements: false

您也可以在其他环境中禁用它。

回到初始问题,Postgres通常COUNT查询速度很慢,尤其是DISTINCT,因此您应该尝试对其进行优化。但由于它是随机峰值,我敢打赌它是由AUTOVACUUM引起的。如果您不熟悉,AUTOVACUUM就像一个垃圾收集器,它从磁盘中删除已删除的行,收集统计信息等。运行它时会产生大量的IO流量,从而减慢其他查询的速度。默认情况下,在表中20%的行发生更改后调用它,您无法准确预测何时发生。可以在夜间或低流量时手动运行。只需在psql中输入VACUUM ANALYZE table_name;即可。

您还可以查看与autovacuum相关的数据库统计信息(上次执行时,更改了多少行等)。最简单的方法是安装https://github.com/heroku/heroku-pg-extras并运行heroku pg:vacuum-stats