3

根据 Heroku 的建议,我有一个创建新的 activerecord 记录的任务,我最近使用 delay_job 和 foreman 将其移动到后台任务

有时这可以正常工作,但有时会导致浏览器中的 Rails 应用程序停止响应。

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

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

validate :hit_database_to_see_if_model_exists?

before_save :get_rows_from_database_and_perform_calculation  

还有一些 INSERT 语句,我确信它们已经进入数据库,因为在终止进程之前/之后记录的数量没有改变

这是我的Procfile:

网络:捆绑 exec rails 服务器瘦 -p $PORT -e $RACK_ENV

工人:捆绑执行耙工作:工作

所以感觉就像我得到一个“堆栈溢出”(哇)。你能解释一下吗:

  • 一般是怎么回事?
  • 在 Rails 中,这种“堆栈溢出”发生在哪里
  • 这些事情是在我按下“Ctrl + C”之后实际发生的,还是当时只是被打印到终端上?
  • 这可能是什么原因造成的?
  • 我该如何调试/修复它?

更新

看起来后台任务正在将某些任务分配给 Web 进程,但直到浏览器被“刺激”后才会执行。在某些情况下,它们都会执行,但如果太多,应用程序就会崩溃。关于可能导致这种情况的任何想法?

更新

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

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

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

这是正常的吗?这是否说明了问题可能是什么?

更新

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

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

击杀:9

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

更新

我在用:

  • 延迟作业 3.0.4
  • 延迟作业活动记录 0.3.3
  • 延迟作业网络 1.1.2
  • 工头 0.60.2

解析度

感谢@Justin 在下面的回答(以及这个相关的问题)。似乎 Ruby 默认会缓冲标准输出,并且该缓冲区溢出,导致应用程序停止响应。我$stdout.sync = true在 config/environments/development.rb 的顶部添加了,问题似乎已经消失了。

4

1 回答 1

3

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

默认情况下,Rails 缓冲日志记录,并在每次 Web 请求后刷新它。一种选择是简单地用更简单的记录器替换记录器

Rails.logger = Logger.new(STDOUT)

您还可以将缓冲记录器配置为更频繁地刷新

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

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

STDOUT.sync = true

至于你更大的问题,

我很惊讶 rails 进程正在运行后台任务。是否有禁用它的选项,至少对于实验而言?

然后是标准的调试工具——所有的数据库调用都让我担心,所以我会尝试各种禁用它们的组合,看看是否有任何改进。尤其是其中两个——例如,如果你的 before_save 钩子改变了模型中的一个值,它可能会触发验证;如果这会重置 before_save 钩子,那么您将有一个循环。

于 2013-01-16T22:34:40.263 回答