我有一个创建新的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)。你能说清楚:
更新
看起来后台任务会将某些任务分配给Web进程,但在浏览器“被激活”之前不会执行。在某些情况下,它们都会执行,但如果有太多应用程序失败。关于可能导致这种情况的任何想法?
更新
我尝试在两个单独的窗口中运行Web和工作进程。
在这种情况下,我无法复制浏览器挂起的问题,并且在每种情况下工作进程都已正确完成。
然而,我确实做了一个有趣的观察,如果我不触摸浏览器,那么网页窗口中就不会出现任何输出。但是,如果我确实触摸了浏览器,那么工作流程当时正在进行的数千行显示在Web窗口中。
这是正常的吗?这是否可以解决问题所在?
更新
在我终止进程后终端输出的底部显示“已杀死:9”
07:45:21系统|将SIGKILL发送到所有进程
被杀:9
这9指的是什么?这不寻常吗?
更新
我正在使用:
解决
感谢@ Justin的回答(和this related question)。似乎Ruby默认缓冲stdout,并且此缓冲区溢出,导致应用程序停止响应。我在config / environments / development.rb的顶部添加了$stdout.sync = true
,问题似乎已经消失。
答案 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挂钩,你就会有一个循环。