Rails 4多线程应用程序 - ActiveRecord :: ConnectionTimeoutError

时间:2014-03-05 19:58:17

标签: ruby-on-rails database multithreading activerecord

我有一个简单的rails应用程序,它从模型的每个实例的远程URL中抓取JSON(让我们称之为A)。然后,应用程序在第一个关联模型下创建一个新数据点。让我们称之为中间模型B和数据点模型C.还有一个前端,让用户以图形/视觉方式浏览这些数据。

因此,层次结构是A有很多 - > B有很多 - > C.我为每个A刮取一个URL,该URL返回一些B的实例,其中包含具有相应B的数据的新C。

在尝试测试/扩展这个应用程序时,我遇到了一个问题,rails会停止处理,挂起一段时间,最后抛出一个“ActiveRecord :: ConnectionTimeoutError无法在5.000秒内获得数据库连接”显然5是只是默认值。

我无法理解为什么会发生这种情况1)没有显式的DB调用,2)日志没有显示任何内幕DB调用发生时它工作3)它有时工作而不是其他。

rails 4 AR和连接池有什么问题?!

几点说明:

  1. 一般算法是为每个模型A生成一个线程,刮取数据,在内存中创建模型C的新实例,最后在一个事务中保存所有C。
  2. 有时候这种方法有效,有时却没有,我无法弄清楚是什么导致它失败。但是,一旦失败,它似乎越来越失败。
  3. 我渴望加载所有模型A和B的开头。
  4. 我在末尾使用一个事务来插入所有新创建的C实例。
  5. 我目前使用resque和resque调度程序来完成这项工作,但我非常怀疑它们是问题的根源,因为它仍然存在,即使我只是做“rails runner Class.do_work”
  6. 任何建议或想法都非常感谢!

2 个答案:

答案 0 :(得分:1)

我相信我找到了这个问题的原因。当您通过

循环关联时
model.association.each do |a|
   #work here
end

Rails做了一些“使用”数据库连接的幕后工作。我把引号用在引号中,因为在我的情况下,我认为结果实际上是从内存中返回的。我渴望加载关联,因此DB实际上从未被命中。

中包裹我的块的初步测试
ActiveRecord::Base.connection_pool.with_connection do 
#something me doing?
end

似乎已经解决了这个问题。

我通过在我正在打印的线程错误消息中添加一个回溯来发现这一点。

-----对于使用resque的人----

我还必须在我的resque.rake文件中添加一点,以使其完全按预期工作。

task 'resque:setup' => :environment do 
  Resque.after_fork do |job|
    ActiveRecord::Base.establish_connection
  end
end

答案 1 :(得分:0)

如果您正在使用

ActiveRecord::Base.transaction do 

    ... code

end

在线程中完成更快的事务,请注意这会锁定数据库。我有一个应用程序在一个线程中为一个非常昂贵的进程执行此操作,它将锁定数据库超过5秒。它更快,但会锁定您的数据库