【问题标题】:Rails 4 : ConnectionTimeoutError on heroku basic planRails 4:heroku基本计划上的ConnectionTimeoutError
【发布时间】:2014-06-05 18:33:21
【问题描述】:

我们正在开发一个simple Rails 4 webapp,由 Heroku 托管并提供免费计划。

最近,我们遇到了一些ActiveRecord::ConnectionTimeoutError - 每隔几天就会出现一次 - 我们并不真正了解其背后的原因。

您可能想查看完整的堆栈here

我们知道 Heroku 为 Postgres 数据库设置了 20 个连接的池限制,这很可能是引发异常的原因。这是我们的猜测:

我们使用 Herku 调度程序每小时启动一个 rake 任务,由于该任务查询数据库,问题可能在于这些连接在使用后没有从池中释放。所以我们试图把所有东西都放在一个块中:

ActiveRecord::Base.connection_pool.with_connection do

  #code with queries

end

但这似乎并不能解决问题。你有更好的建议/解释吗?

非常感谢任何帮助和/或见解,以及我们应该如何调试此问题。


PS:我们也尝试在专用的初始化器中添加以下代码,但并没有解决问题

Rails.application.config.after_initialize do
  ActiveRecord::Base.connection_pool.disconnect!

  ActiveSupport.on_load(:active_record) do
    config = ActiveRecord::Base.configurations[Rails.env] ||
                Rails.application.config.database_configuration[Rails.env]
    config['reaping_frequency'] = ENV['DB_REAP_FREQ'] || 10 # seconds
    config['pool']              = ENV['DB_POOL']      || 20
    ActiveRecord::Base.establish_connection(config)
  end
end

【问题讨论】:

  • 你只有1个进程?请记住,如果您有伙伴或正在运行的东西,他们必须共享 20 个连接......
  • 我们不使用 Sidekiq,但我们使用 Heroku 调度程序调用 rake,每小时一次。这需要很少的查询......这就是重点吗?
  • hm,取决于您的用户负载... rake 任务和错误同时发生?
  • 用户负载并没有那么高——我们从来没有同时拥有 20 个用户。无论如何,由于“heroku 日志”问题,我无法获得错误的准确时间
  • 尝试使用github.com/kch/rack-timeout。可能会有所帮助

标签: ruby-on-rails postgresql heroku


【解决方案1】:

根据我的经验,这些问题将出现在基本的 Heroku 计划中。有许多方法可以在不增加成本的情况下降低频率。但是,基本/爱好堆栈的发生率永远不会达到 0%。

根据我的经验,这就是为什么……在您点击“高级 yanari”之前,您不会获得高可用性。与免费的 99.5% 相比,您可以获得 99.95% 的预期正常运行时间。听起来不多,但 Heroku 额外收取 150 美元是有原因的(与“标准 yanari”计划相比)。

在对连接池、获取频率和分叉进行所有优化之后,如果您的进程无法访问数据库服务器,您将获得超时。如果这是唯一的原因,它会很少发生,这可能是你的情况。直到我升级到“premium-yanari”后,这种看似随机的超时才停止发生。

我不建议您开始支付 200 美元/月作为解决方案。您可以通过以下一些建议接近零。调整并发、数据库连接和尝试各种选项(如超时)需要一些跟踪和错误——因为似乎没有即插即用的公式可以为您提供所有这些参数的完美组合。

1) 迁移到 Unicorn 以更好地控制您的流程和数据库连接。这是一个示例 unicorn.rb 文件https://gist.github.com/blotto/8005531b9c94f3732240

2) 增加您的超时时间(目前为 5 秒)。见 unicorn.rb :

 timeout ENV['REQUEST_TIMEOUT'].to_i > 0 ?  ENV['REQUEST_TIMEOUT'].to_i : 15

3) 确保您使用的是最新的稳定 Rails 4.1.1。由于 4.0.x 确实存在一些 Postgres 适配器问题。见https://github.com/rails/rails/issues/12867

【讨论】:

  • 不应该是ENV['REQUEST_TIMEOUT'].to_i > 5吗?
  • @Tamer ,不 - 该条件只是测试该环境变量是否存在。 nil.to_i == 0。这样可以确保超时设置具有有效的默认值
猜你喜欢
  • 2014-02-01
  • 2013-07-03
  • 1970-01-01
  • 2016-12-26
  • 2013-09-24
  • 2021-06-30
  • 1970-01-01
  • 2016-04-07
  • 1970-01-01
相关资源
最近更新 更多