如何调试Rails连接池的使用?

Joe*_*Joe 5 activerecord ruby-on-rails sidekiq rails-activejob

我遇到了Sidekiq工人的问题.

ActiveRecord::ConnectionTimeoutError: could not obtain a database connection within 5.000 seconds (waited 5.000 seconds)
Run Code Online (Sandbox Code Playgroud)

我正在遵循有关使用ActiveRecord::ConnectionTimeoutError和适当大的连接池的建议.

我想知道我是否正在耗尽连接池.我记录sizeconnections.lengthActiveRecord::Base.connection_pool,但他们留在一个恒定的大小= 100 connections.length = 5,这表明这不是一个资源泄漏问题.

我的MySQL服务器配置为允许最多400个并发连接.

我的工作最终看起来像这样:

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
Run Code Online (Sandbox Code Playgroud)

这是诊断造成这种情况的正确方法,无论是资源匮乏还是泄漏?是否有其他技术可以解决为什么会发生这种情况?

Jar*_*eck 7

尝试 ActiveRecord::ConnectionAdapters::ConnectionPool#stat

ActiveRecord::Base.connection_pool.stat 
# => { size: 15, connections: 1, busy: 1, dead: 0, idle: 0, waiting: 0, checkout_timeout: 5 }
Run Code Online (Sandbox Code Playgroud)

来自connection_adapters/abstract/connection_pool.rb,在 activerecord 5.2.2.1 中。


Bor*_*aMa 5

ActiveRecord::ConnectionTimeoutError可在我看来只发生在一个场景-当有这么多线程想要使用DB连接,游泳池是疲惫,甚至等待空闲连接不帮助(从学源代码)。

在你的情况下,这很奇怪。您仅使用 25 个工作线程,但池设置为 100 个连接,因此有足够的储备。我仍然怀疑您必须在某处生成线程。也许你在你的工作中做了一些线程?也许您使用 gem 在您的工作中创建线程?

无论如何,如果您能够重现异常,我建议捕获它并在它发生时获取所有线程的列表,如下所示:

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
Run Code Online (Sandbox Code Playgroud)

我预计会有 100 个或更多线程,您应该看到它们从回溯中被卡住的确切位置。