如何调试 Rails 连接池的使用情况?
Posted
技术标签:
【中文标题】如何调试 Rails 连接池的使用情况?【英文标题】:How to debug Rails connection pool usage? 【发布时间】:2016-08-01 23:40:47 【问题描述】:我遇到了 Sidekiq 工作人员的问题。
ActiveRecord::ConnectionTimeoutError: could not obtain a database connection within 5.000 seconds (waited 5.000 seconds)
我正在遵循有关使用 ActiveRecord::ConnectionTimeoutError
和适当大的连接池的建议。
我想知道我是否耗尽了连接池。我正在从ActiveRecord::Base.connection_pool
记录size
和connections.length
,但它们的大小保持不变 = 100 个连接。长度 = 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
这是诊断导致此问题的原因的正确方法吗,无论是资源匮乏还是泄漏?我可以使用其他技术来找出为什么会发生这种情况吗?
【问题讨论】:
database.yml
中定义的连接池大小是多少?你使用了多少个 sidekiq 工作线程?
Pool定义为100,如connection_pool.size所示,25个worker。
【参考方案1】:
试试ActiveRecord::ConnectionAdapters::ConnectionPool#stat
ActiveRecord::Base.connection_pool.stat
# => size: 15, connections: 1, busy: 1, dead: 0, idle: 0, waiting: 0, checkout_timeout: 5
来自connection_adapters/abstract/connection_pool.rb
,在活动记录 5.2.2.1 中。
【讨论】:
感谢您的回复。可悲的是,我无法再尝试这个了。【参考方案2】:在我看来,ActiveRecord::ConnectionTimeoutError
只能在一种情况下发生 - 当有这么多线程想要使用 DB 连接时,池已用尽,甚至等待空闲连接也无济于事(从source code获悉)。
在你的情况下,这很奇怪。您只使用了 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
我预计会有 100 个或更多线程,您应该从回溯中看到它们究竟卡在哪里。
【讨论】:
非常感谢。我会试试的。我自己没有编写任何线程,但谁知道其他库在做什么! 你找到什么了吗? 没有。我减少了 sidekiq 工作人员的数量并且没有错误。这将被列入长期调查名单。感谢您的检查。以上是关于如何调试 Rails 连接池的使用情况?的主要内容,如果未能解决你的问题,请参考以下文章