很慢:ActiveRecord::QueryCache#call

Very slow: ActiveRecord::QueryCache#call

我在 heroku 上有一个应用程序,运行 在 Puma 上:

workers 2
threads_count 3
pool 5

看起来有些请求卡在了中间件中,这使得应用程序非常慢(非常!)。 我已经看到其他人讨论过这个问题,但目前还没有解决方案。

如果您有任何提示,请告诉我。

!

!

我最近开始发现花在 ActiveRecord::QueryCache#call 上的时间激增。查看源代码后,我决定尝试使用连接到生产环境的 Rails 控制台中的 ActiveRecord::Base.connection.clear_query_cache 清除缓存。我得到的错误是 PG::ConnectionBad: could not fork new process for connection: Cannot allocate memory 这至少让我想到了另一个 SO 问题 Heroku Rails could not fork new process for connection: Cannot allocate memory

我为 Heroku 支持工作,Middleware/Rack/ActiveRecord::QueryCache#call 是 New Relic 经常报告的一个问题。不幸的是,这通常是转移注意力的问题,因为每次问题的根源都在别处。

QueryCache 是 Rails 首先尝试检查连接以供使用的地方,因此连接的任何问题都会在这里显示为正在等待 'stuck' 的请求。这并不意味着数据库服务器一定没有连接(如果你有 Postgres 的 Librato 图表,它们会显示这一点)。这可能意味着某些原因导致某些数据库连接进入错误状态,并且正在等待新的连接请求。这可能发生在旧版本的 Puma 中,其中使用了多个线程并设置了 reaping_frequency - 如果某些连接进入错误状态而其他连接被收割,这将导致问题。

一些高级建议如下:

  • 升级 Ruby & Puma
  • 如果使用 rack-timeout gem,也升级它

这些升级通常会有帮助。如果没有,还有其他选项需要考虑,例如从线程切换到基于工作进程的进程或使用 Postgres 连接池(如 PgBouncer)。我们有更多关于配置并发 Web 服务器以与 Postgres 一起使用的建议:https://devcenter.heroku.com/articles/concurrency-and-database-connections

我会回答我自己的问题: 我只需要检查对我的数据库的所有查询。其中一个花费了很长时间,即使不经常请求,它也会在之后相当长的一段时间内降低整个服务器的速度(即使在该过程完成后,有一种 "traffic jam" on服务器)。 解决方案: 检查对数据库的所有查询,修复最慢的查询(这可能只是意味着将其分解为几个步骤,也可能意味着在没有流量的晚上 运行 等)。 修复此查询后,一切都会恢复正常。