Ruby on rails 如何调试Rails连接池的使用?
我遇到了Sidekiq工人的问题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记录
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工人的数量,没有错误。这将列入长期调查清单。谢谢你的检查。谢谢你的回复。可悲的是,我再也不能尝试这个了。