capistrano部署后,锁定的delayed_job行在数据库中徘徊

时间:2013-05-12 19:46:32

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

每当我使用capistrano部署或运行​​cap production delayed_job:restart时,我最终都会将当前正在运行的delayed_job行保持锁定状态。

delayed_job进程已成功停止,新的delayed_job进程已启动,新进程将锁定新行。问题是最后一个进程'仍然在那里&标记为已锁定。所以我必须手动进入数据库,删除该行,然后手动将该作业添加回队列,以便新的delayed_job进程进入。

有没有办法清理数据库&重新排队上一个作业会自动发生吗?

2 个答案:

答案 0 :(得分:2)

我有同样的问题。只要工作被强行杀死,就会发生这种情况。部分问题是工作进程由守护进程gem而不是delayed_job本身管理。我正在研究解决这个问题的方法,例如:

  • 在守护进程强行终止之前设置更长的超时(在delayed_joob或守护进程的文档中没有任何内容)
  • 在启动delayed_job workers之前清除锁定

如果我想出一个解决方案,我会在这里回复。

答案 1 :(得分:0)

调整您的守护进程等待时间或在 SIGINT 上引发异常。

@John Carney 是对的。简而言之,所有 delayed_job 工人在重新部署时都会收到类似 SIGINT(不错的中断)的消息。默认情况下,delayed_job 工作人员将完成他们当前的工作(如果他们正在处理一项工作),然后正常终止。

但是,如果他们正在处理的作业是一个运行时间较长的作业,那么守护程序管理器会等待一段时间,然后才会感到恼火并发送更严重的中断信号,例如 SIGTERM 或 { {1}}。此等待时间以及发送的内容实际上取决于您的设置和配置。

当这种情况发生时,SIGKILL 工作器会立即被杀死,而无法完成其正在处理的工作,甚至无法自行清理并将工作标记为不再锁定。

这最终会导致一个标记为“锁定”但锁定到不再存在的进程/工人的“搁浅”作业。不好。

这就是问题的症结所在以及正在发生的事情。要解决这个问题,您有两个主要选择,具体取决于您的工作内容(我们两者都使用):

1.收到中断时引发异常。

您可以通过将 delayed_job 配置设置为 raise_signal_exceptions:term 来实现:

true

此配置选项接受 Delayed::Worker.raise_signal_exceptions = :term :termtrue(默认)。您可以阅读有关原始提交 here 的更多信息。

我会先尝试使用 false,看看是否能解决您的问题。如果没有,您可能需要将其设置为 :term

设置为 true:term 将优雅地引发异常并解锁作业,以便另一个 true 工人接手并开始处理它。

将其设置为 delayed_job 意味着您的 true 工人甚至不会尝试完成他们正在从事的当前工作。他们会立即引发异常,解锁工作并自行终止。

2.调整您的工作人员在重新部署时被中断/终止/杀死的方式。

这实际上取决于您的重新部署等。在我们的例子中,我们使用 Cloud66 来处理部署,所以我们只需要使用它们进行配置。但这就是我们的样子:

delayed_job

在重新部署时,这会告诉守护程序管理器按照以下步骤将每个 stop_sequence: int, 172800, term, 90, kill # Allows long-running delayed jobs to finish before being killed (i.e. on redeploy). Sends SIGINT, waits 48 hours, sends SIGTERM, waits 90 seconds, sends SIGKILL. 工人:

  1. 发送delayed_job
  2. 等待 172800 秒(2 天) - 我们有非常长时间运行的作业。
  3. 发送 SIGINT,如果工人还活着。
  4. 等待 90 秒。
  5. 发送 SIGTERM,如果工人还活着。

无论如何,这应该有助于让您走上正确的轨道,为自己正确配置。

我们通过设置长时间超时以及在收到 SIGKILL 时引发异常来使用这两种方法。这确保了如果有一个作业超过了 2 天的限制,它至少会引发异常并解锁该作业,让我们能够进行调查,而不是仅仅留下一个被锁定到不再存在的进程的搁浅作业。