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

Ruby on rails 如何调试Rails连接池的使用?,ruby-on-rails,activerecord,sidekiq,rails-activejob,Ruby On Rails,Activerecord,Sidekiq,Rails Activejob,我遇到了Sidekiq工人的问题 ActiveRecord::ConnectionTimeoutError: could not obtain a database connection within 5.000 seconds (waited 5.000 seconds) 我遵循有关使用ActiveRecord::ConnectionTimeoutError和适当大的连接池的建议 我想知道我是否耗尽了连接池。我正在从ActiveRecord::Base.connection\u pool记录

我遇到了Sidekiq工人的问题

ActiveRecord::ConnectionTimeoutError: could not obtain a database connection within 5.000 seconds (waited 5.000 seconds)
我遵循有关使用
ActiveRecord::ConnectionTimeoutError
和适当大的连接池的建议

我想知道我是否耗尽了连接池。我正在从
ActiveRecord::Base.connection\u pool
记录
size
connections.length
,但它们保持恒定的大小=100个连接。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
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
classmyjob

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

在我看来,这种
ActiveRecord::ConnectionTimeoutError
只能在一种情况下发生-当有太多线程想要使用DB连接时,池已耗尽,甚至等待空闲连接也无济于事(从中了解到)

对你来说,这很奇怪。您只使用25个工作线程,但池设置为100个连接,因此有足够的保留空间。我仍然怀疑你一定在某个地方产生了线程。也许你在工作中会穿线?也许你使用一个gem在你的工作中创建线程

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

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
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个或更多线程,您应该可以从回溯中看到它们的确切位置。

尝试
ActiveRecord::ConnectionAdapters::ConnectionPool\stat

ActiveRecord::Base.connection_pool.stat 
# => { size: 15, connections: 1, busy: 1, dead: 0, idle: 0, waiting: 0, checkout_timeout: 5 }

从activerecord 5.2.2.1中的
connection\u adapters/abstract/connection\u pool.rb

数据库.yml中定义的连接池大小是多少?您使用了多少sidekiq工作线程?池定义为100,如connection_Pool.size,25个工作线程所示。非常感谢。我试试看。我自己并没有编造任何线程,但谁知道其他库在做什么呢!你找到什么了吗?没有。我减少了sidekiq工人的数量,没有错误。这将列入长期调查清单。谢谢你的检查。谢谢你的回复。可悲的是,我再也不能尝试这个了。