我在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
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
答案 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