Sidekiq и фоновое задание часов на Redis, Rails, Heroku, только обновление некоторых
Я выполняю фоновое задание на многих записях с помощью Rails, Sidekiq, Redis и Clockwork на Heroku, но я продолжаю получать эту ошибку на многих записях, которые он пытается обновить с помощью API:
ActiveRecord::ConnectionTimeoutError: could not obtain a database connection within 5.000 seconds
Вот мои файлы:
Unicorn:
worker_processes Integer(ENV["WEB_CONCURRENCY"] || 3)
timeout 15
preload_app true
before_fork do |server, worker|
Signal.trap 'TERM' do
puts 'Unicorn master intercepting TERM and sending myself QUIT instead'
Process.kill 'QUIT', Process.pid
end
if defined?(ActiveRecord::Base)
ActiveRecord::Base.connection.disconnect!
end
end
after_fork do |server, worker|
Signal.trap 'TERM' do
puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT'
end
if defined?(ActiveRecord::Base)
config = Rails.application.config.database_configuration[Rails.env]
config['reaping_frequency'] = ENV['DB_REAP_FREQ'] || 10 # seconds
config['pool'] = ENV['DB_POOL'] || 5
ActiveRecord::Base.establish_connection(config)
end
end
База данных:
production:
adapter: postgresql
encoding: unicode
database: production
pool: 25
timeout: 10000
Часы:
every(24.hours, 'Update') do
sites = Site.order(:id).pluck(:id)
Site.each do |site|
UpdatePosts.perform_async(site)
end
end
UpdatePosts
class UpdatePosts
include Sidekiq::Worker
sidekiq_options retry: false
def perform(site_id)
...
end
end
1 ответ
Ошибка, которую вы видите, вызвана тем, что больше потоков пытается получить соединение из пула соединений ActiveRecord, чем в этом пуле. Когда поток запрашивает соединение, но оно не освобождается в течение 5 секунд, возникает ошибка, которую вы видите.
В Sidekiq число рабочих потоков больше, чем размер пула ActiveRecord по умолчанию. Это вызывает ошибки, подобные этой, под нагрузкой.
Вы можете настроить размер пула БД в соответствии с количеством потоков Sidekiq в вашем config/initializers/sidekiq.rb
файл с использованием кода, подобного этому:
Sidekiq.configure_server do |config|
if(database_url = ENV['DATABASE_URL'])
pool_size = Sidekiq.options[:concurrency] + 2
ENV['DATABASE_URL'] = "#{database_url}?pool=#{pool_size}"
ActiveRecord::Base.establish_connection
end
end
Хотя вы пытались увеличить pool_size
в вашем database.yml
файл, эта конфигурация перезаписывается при развертывании в Heroku и полностью управляется DATABASE_URL
переменная окружения.