Rails:如何调试localhost没有响应delayed_job / foreman

时间:2013-01-09 08:29:53

标签: ruby-on-rails delayed-job foreman

我有一个创建新的activerecord记录的任务,我最近使用delayed_job和foreman as recommended by Heroku

将其移至后台任务

有时这很好用,但有时会导致浏览器中的Rails应用程序停止响应。

此时我可以从数据库中看到所有延迟的作业都已完成,并且所有新记录都已创建。

然而,当我杀死进程时,我得到了更多的11,200行终端输出。这主要包括Web进程在模型上执行两个方法,这两个方法都涉及对数据库的调用:

validate :hit_database_to_see_if_model_exists?

before_save :get_rows_from_database_and_perform_calculation  

还有一些INSERT语句我肯定已经打到了数据库,因为在杀死进程之前/之后记录数没有变化

这是我的Procfile:

  

web:bundle exec rails server thin -p $ PORT -e $ RACK_ENV

     

worker:捆绑exec佣金工作:工作

所以感觉我得到了'堆栈溢出'(woop)。你能说清楚:

  • 一般情况如何?
  • 在Rails中,“堆栈溢出”正在发生
  • 在点击'Ctrl + C'或者只是在那时打印到终端后,这些事情是否真的发生了?
  • 可能导致这种情况的原因是什么?
  • 我如何调试/修复它?

更新

看起来后台任务会将某些任务分配给Web进程,但在浏览器“被激活”之前不会执行。在某些情况下,它们都会执行,但如果有太多应用程序失败。关于可能导致这种情况的任何想法?

更新

我尝试在两个单独的窗口中运行Web和工作进程。

在这种情况下,我无法复制浏览器挂起的问题,并且在每种情况下工作进程都已正确完成。

然而,我确实做了一个有趣的观察,如果我不触摸浏览器,那么网页窗口中就不会出现任何输出。但是,如果我确实触摸了浏览器,那么工作流程当时正在进行的数千行显示在Web窗口中。

这是正常的吗?这是否可以解决问题所在?

更新

在我终止进程后终端输出的底部显示“已杀死:9”

  

07:45:21系统|将SIGKILL发送到所有进程

     

被杀:9

这9指的是什么?这不寻常吗?

更新

我正在使用:

  • delayed_job 3.0.4
  • delayed_job_active_record 0.3.3
  • delayed_job_web 1.1.2
  • 领班0.60.2

解决

感谢@ Justin的回答(和this related question)。似乎Ruby默认缓冲stdout,并且此缓冲区溢出,导致应用程序停止响应。我在config / environments / development.rb的顶部添加了$stdout.sync = true,问题似乎已经消失。

1 个答案:

答案 0 :(得分:3)

这只是部分答案,但它可以帮助您进行调试。

Rails默认缓冲日志记录,并在每次Web请求后刷新它。一种选择是简单地用simpler logger

替换记录器
Rails.logger = Logger.new(STDOUT)

您还可以configure the buffered logger to flush more often

Rails.logger.auto_flushing = (Rails.env.development? || Rails.env.test?)

您还必须小心STDOUT。在我当前的项目中,我在config.ru和后台启动时启用了stdout刷新(我使用的是sidekiq,所以启动过程可能会有所不同)

STDOUT.sync = true

关于你的大问题,

我很惊讶rails进程正在运行后台任务。有没有选项可以禁用它,至少对于实验来说?

然后有标准的调试工具 - 保存的所有数据库调用都让我担心,所以我会尝试各种禁用它们的组合来查看是否有任何改进。特别是有两个 - 例如,如果你的before_save钩子改变了模型中的一个值,它可能会触发一个验证;如果重置了before_save挂钩,你就会有一个循环。