Фоновая задача Sidekiq и Clock на Redis, Rails, Heroku Обновление только некоторых

Я запускаю фоновую задачу для многих записей с помощью Rails, Sidekiq, Redis и Clockwork на Heroku, но я продолжаю получать эту ошибку для многих записей, которые он пытается обновить с помощью API:

ActiveRecord::ConnectionTimeoutError: could not obtain a database connection within 5.000 seconds

Вот мои файлы:

Единорог:

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

Обновление сообщений

class UpdatePosts
    include Sidekiq::Worker
    sidekiq_options retry: false

    def perform(site_id)
    ...
    end
end

person user2270029    schedule 17.02.2014    source источник
comment
Вы проверили максимальное количество подключений, которое поддерживает ваш сервер Postgres? Если вы достигаете предела, это может объяснить ошибку...   -  person Matt Jones    schedule 17.02.2014
comment
Это 20 подключений. Есть ли способ заставить его работать с этим или мне нужно обновить мой сервер?   -  person user2270029    schedule 17.02.2014


Ответы (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.

person Winfield    schedule 17.02.2014
comment
Я пытался понять это навсегда. Большое спасибо. - person user2270029; 17.02.2014