3

每当我使用 capistrano 或 run 部署时cap production delayed_job:restart,我最终都会使当前运行的延迟作业行保持锁定状态。

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

有没有办法让数据库清理和上一个作业的重新排队自动发生?

4

2 回答 2

3

我也有同样的问题。每当作业被强行杀死时,就会发生这种情况。部分问题是工作进程由守护进程 gem 管理,而不是 delay_job 本身。我目前正在研究解决此问题的方法,例如:

  • 在守护进程强制终止之前设置更长的超时时间(在延迟作业或守护进程的文档中没有关于此的内容)
  • 在启动 delay_job 工作人员之前清除锁

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

于 2013-06-30T07:27:32.713 回答
0

调整您的守护程序等待时间或在SIGINT.

@约翰卡尼是正确的。简而言之,所有delayed_job工作人员在重新部署时都会收到类似SIGINT(很好的中断)的信息。delayed_job默认情况下,worker 将完成他们当前的工作(如果他们正在从事一项工作),然后优雅地终止。

但是,如果他们正在处理的工作是一项运行时间较长的工作,那么守护程序管理器会等待一段时间,然后才会感到烦恼并发送更严重的中断信号,例如 a SIGTERMor SIGKILL。这个等待时间和发送的内容实际上取决于您的设置和配置。

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

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

这是问题的症结所在,也是正在发生的事情。为了解决这个问题,您有两个主要选择,具体取决于您的工作(我们同时使用):

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

您可以通过将raise_signal_exceptions配置设置为:term或来做到这一点true

Delayed::Worker.raise_signal_exceptions = :term

此配置选项接受:term,truefalse(默认)。您可以在此处阅读有关原始提交的更多信息。

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

设置为:termortrue将优雅地引发异常并解锁工作以供其他delayed_job工作人员接手并开始工作。

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

2. 调整你的工人在重新部署时被打断/终止/杀死的方式。

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

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.

在重新部署时,这会告诉守护进程管理器对每个工作人员执行以下步骤delayed_job

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

无论如何,这应该可以帮助您走上正确的轨道,为自己正确配置它。

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

于 2021-01-05T15:27:29.610 回答