2016-04-11 3 views
5

У меня проблемы с работниками Sidekiq.Как отладить использование пула соединений Rails?

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

Я следую рекомендации по использованию ActiveRecord::ConnectionTimeoutError и соответствующим образом большого пула соединений.

Я хочу узнать, исчерпал ли я пул подключений. Я регистрирую size и connections.length от ActiveRecord::Base.connection_pool, но они остаются с постоянным размером = 100 connections.length = 5. Это говорит о том, что это не проблема утечки ресурсов.

Мой сервер MySQL настроен на разрешение до 400 одновременных подключений.

My Job закончился выглядеть так:

class MyJob < ActiveJob::Base 
    queue_as :default  
    rescue_from StandardError do |exception| 
    # clear connections on exception. Not sure if this is a good idea or not. 
    ActiveRecord::Base.clear_active_connections!  
    end 

    def perform() 
    logger.info "size" 
    logger.info ActiveRecord::Base.connection_pool.instance_eval { @size } 
    logger.info "connections" 
    logger.info ActiveRecord::Base.connection_pool.instance_eval { @connections }.length 

    # Ensure connections come from connection pool. 
    ActiveRecord::Base.connection_pool.with_connection do |conn| 
     # do stuff 
    end 
    end 
end 

Это правильный способ диагностировать то, что причиной этого, является ли это голодание ресурс или утечка? Существуют ли другие методы, которые я могу использовать, чтобы понять, почему это происходит?

+0

Каков размер пула соединений, определенный в вашем 'database.yml'? Сколько боковых рабочих потоков вы используете? – BoraMa

+0

Пул определяется как 100, как показано в connection_pool.size, 25 рабочих. – Joe

ответ

2

Это ActiveRecord::ConnectionTimeoutError может на мой взгляд, происходит только в одном случае - когда есть так много потоков, которые желают использовать соединения DB, что пул будет исчерпан и даже ждет бесплатное подключение не помогает (как узнал от source code).

В вашем случае это странно. Вы используете только 25 рабочих потоков, но в пуле установлено 100 соединений, поэтому есть много резервов. Я все еще подозреваю, что у вас должны появляться нитки. Возможно, вы делаете некоторые потоки на своих рабочих местах? Возможно, вы используете драгоценный камень, который создает потоки на ваших рабочих местах?

Во всяком случае, если вы в состоянии воспроизвести исключение, я хотел бы предложить, чтобы поймать его и получить список всех потоков в данный момент происходит, что-то вроде этого:

begin 
    # job stuff...  
rescue ActiveRecord::ConnectionTimeoutError 
    puts "listing #{Thread.list.count} threads:" 
    Thread.list.each_with_index do |t,i| 
    puts "---- thread #{i}: #{t.inspect}" 
    puts t.backtrace.take(5) 
    end 
end 

Я ожидаю, что будет 100 или более потоков, и вы должны увидеть, где именно они застряли от обратной линии.

+0

Блестящая благодарность. Я попробую. Я не прячусь ни на какие темы, но кто знает, что делают другие библиотеки! – Joe

+0

Вы еще что-нибудь нашли? – BoraMa

+1

Нет. Я сократил количество рабочих сторонников и не имел ошибок. Это происходит в списке долгосрочных расследований. Спасибо за проверку. – Joe