在Rails应用程序中线程内的日志记录

10
我有一个Rails应用程序,其中少数动作需要较长的计算时间。为了避免管理这些操作作为后台任务的复杂性,我发现我可以将处理拆分成多个线程,并使用具有多核心的JRuby,以确保所有线程在合理的时间内完成。(客户已经表达了保持这种方法而不是在后台运行任务的浓厚兴趣。)
问题是在这些线程中写入Rails日志器不起作用。日志文件中没有显示任何内容。我找到了一些关于此问题的参考资料,但没有解决方案。我不介意在我的代码中插入puts来帮助调试,但stdout似乎被glassfish gem应用服务器吃掉了。
是否有人成功地在Rails ruby线程内进行记录而不每次创建新日志?

更新:我发现在线程中使用puts会显示在Glassfish日志文件中。我不确定为什么之前没有看到这个;可能最初是在另一个(非主)线程中生成的线程中进行测试。无论如何,出于调试目的,我在日志文件中看到了对STDOUT的写入,所以我很高兴。 - Mark Westling
2个回答

7
我曾经也为同样的问题苦恼过。对我来说,答案如下:
Thread.new do
  begin
    ...
  ensure
    Rails.logger.flush
  end
end

0

我了解你对于后台任务的担忧,但请记住,在Rails中启动线程可能是一件令人害怕的事情。该框架几乎没有为多线程做出任何规定,这意味着您必须将所有Rails对象视为不支持线程安全。即使是数据库连接也会变得棘手。

至于记录器:标准的Ruby记录器类应该是线程安全的。但即使Rails使用它,您也无法控制Rails应用程序对其的操作。例如,基准测试机制将通过切换级别“静音”记录器。

我建议避免使用Rails记录器。如果您想要使用线程,请在线程内创建一个新的记录器,以记录该操作的消息。如果您不想为每个线程创建新日志,您还可以尝试在运行时创建一个线程安全的日志记录对象,以便每个线程都可以访问。

如果是我,我可能会再看看后台作业的解决方案。虽然DRb看起来像是一场噩梦,但"bj"似乎很好用;尽管需要一些工作才能让它在JRuby上运行。还有一个选择是使用JRuby的Java调度程序,参见http://www.jkraemer.net/2008/1/12/job-scheduling-with-jruby-and-rails

感谢提供的信息和建议,但现在我会继续使用线程方法,因为它除了日志记录以外已经很好地实现了。我没有在任何线程中使用可疑的gems/插件,并且我小心地使用互斥锁来防止竞态条件。我对使用Rails日志记录器的兴趣只是为了方便调试,我通过仅在JRUBY_VERSION定义时使用线程,否则顺序运行相同的代码来解决了这个问题。不管怎样,还是谢谢! - Mark Westling

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接