Heroku

时间:2016-08-19 15:46:30

标签: ruby-on-rails postgresql activerecord heroku sidekiq

我在Heroku中反复ActiveRecord::ConnectionTimeoutError与Sidekiq合作。这是完整的错误:

ActiveRecord::ConnectionTimeoutError: could not obtain a connection from the pool within 5.000 seconds (waited 5.008 seconds); all pooled connections were in use
  • 我使用1 dyno for Sidekiq,大小为Performance L,并发为15
  • 对于网络服务器,我使用1 dyno与2 puma工作者和15个线程,因此总数为(1 * 2 * 15 = 30)。
  • 我的数据库池大小为20(我使用Standard-0 postgres,最多有120个连接)。

那么当连接池大小大于可以使用的最大连接数时,如何获得此错误?总计(15 + 40 = 45)从120

这是我的配置文件:

- condig/sidekiq.yml

    concurrency: 15
    :queues:
      - myapp

- condig/inititalizers/sidekiq.rb

Sidekiq.configure_client do |config|
  config.client_middleware do |chain|
    chain.add Sidekiq::Status::ClientMiddleware
  end
end

Sidekiq.configure_server do |config|
  config.redis = { url: ENV["REDISTOGO_URL"] } if ENV["REDISTOGO_URL"].present?

  config.server_middleware do |chain|
    chain.add Sidekiq::Status::ServerMiddleware, expiration: 30.minutes
  end
  config.client_middleware do |chain|
    chain.add Sidekiq::Status::ClientMiddleware
  end
end

Sidekiq.configure_client do |config|
  config.redis = { url: ENV["REDISTOGO_URL"] } if ENV["REDISTOGO_URL"].present?
end

if Rails.env.production?
  Sidekiq.configure_server do |config|
    config.redis = { url: ENV["REDISTOGO_URL"] }
  end

  Sidekiq.configure_client do |config|
    config.redis = { url: ENV["REDISTOGO_URL"] }
  end
end

Sidekiq.default_worker_options = {
  queue: "myapp",
  backtrace: true,
  retry: false
}

- config/puma

workers Integer(ENV["WEB_CONCURRENCY"] || 2)
threads_count = Integer(ENV["RAILS_MAX_THREADS"] || 15)
threads threads_count, threads_count

preload_app!

rackup      DefaultRackup
port        ENV["PORT"]     || 3000
environment ENV["RACK_ENV"] || "development"

on_worker_boot do
  ActiveRecord::Base.establish_connection
end

- database.yml

production:
  pool: 20

2 个答案:

答案 0 :(得分:0)

在这种情况下的问题是puma vs数据库配置,你的puma服务器将尝试产生30个线程,但数据库池的配置是为所有这些共享,设置为只有20个连接(它忽略了你的数据库可以处理120只使用配置中的内容),所以10个美洲狮线程将不断地发现该错误。

参考:https://devcenter.heroku.com/articles/concurrency-and-database-connections

答案 1 :(得分:0)

thread显示了work()方法完成后Active Record如何正确释放连接。它描述了运动鞋的问题,但由于它是Active Record问题,因此也可以用于Sidekiq。

def work(msg)
  id = JSON.parse(msg)['id']
  ActiveRecord::Base.connection_pool.with_connection do
    user = User.find(id)
    user.name="Homer Simpson"
    user.save
  end
  ack!
end