ruby-on-rails 锁定的delayed_job行在capistrano部署后仍留在数据库中

izj3ouym  于 7个月前  发布在  Ruby
关注(0)|答案(2)|浏览(80)

每当我使用capistrano部署或运行cap production delayed_job:restart时,我最终都会锁定当前运行的delayed_job行。
delayed_job进程成功停止,新的delayed_job进程启动,新进程锁定了新的行。问题是最后一个进程的行仍然在那里,标记为锁定。所以我必须手动进入数据库,删除该行,然后手动将该作业添加回队列,以便新的delayed_job进程访问。
是否有一种方法可以自动进行数据库清理和重新排队?

rta7y2nd

rta7y2nd1#

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

  • 在守护进程强制终止之前设置一个更长的超时时间(在delayed_joob或守护进程的文档中没有关于这个的内容)
  • 在启动delayed_job worker之前清除锁

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

h79rfbju

h79rfbju2#

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

@John Carney是正确的。简而言之,所有的delayed_job worker在重新部署时都会收到类似SIGINT(漂亮的中断)的消息。默认情况下,delayed_job worker会完成当前的作业(如果他们正在处理一个作业),然后优雅地终止。
但是,如果他们正在处理的作业是一个运行时间较长的作业,则Daemon管理器在生气并发送更严重的中断信号(如SIGTERMSIGKILL)之前会等待一段时间。此等待时间以及发送的内容实际上取决于您的设置和配置。
当这种情况发生时,delayed_job工作线程会立即被杀死,而无法完成它正在处理的作业,甚至无法在自己完成后进行清理,并将作业标记为不再锁定。
这最终导致一个“搁浅”的作业,它被标记为“锁定”,但被锁定到一个不再存在的进程/worker。
这就是问题的症结所在。要解决这个问题,你有两个主要的选择,这取决于你的工作是什么样子的(我们两个都用):

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

您可以通过将raise_signal_exceptions配置设置为:termtrue来完成此操作:

Delayed::Worker.raise_signal_exceptions = :term

字符串
此配置选项接受:termtruefalse(默认)。您可以阅读有关原始提交here的更多信息。
我会先尝试使用:term,看看这是否解决了你的问题。如果没有,你可能需要将它设置为true
设置为:termtrue将正常引发异常并解锁作业,以便另一个delayed_job工作进程拾取作业并开始处理它。
将其设置为true意味着您的delayed_job工作线程甚至不会尝试完成他们正在处理的当前作业。他们将立即引发异常,解锁作业并终止自己。

2.调整您的工作线程在重新部署时的中断/终止/终止方式。

这真的取决于你的重新部署,等等。在我们的例子中,我们使用Cloud 66来处理部署,所以我们只需要用它们来配置它。但这是我们的样子:

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
1.等待172800秒(2天)-我们有 * 非常 * 长时间运行的作业。
1.如果worker还活着,发送SIGTERM
1.等待90秒。
1.如果worker还活着,发送SIGKILL
无论如何,这应该有助于让你走上正确的轨道,为自己正确地配置它。
我们使用这两种方法,设置一个较长的超时时间,并在收到SIGTERM时引发异常。这确保了如果有一个作业运行超过2天的限制,它至少会引发一个异常并解锁作业,从而允许我们进行调查,而不仅仅是留下一个被锁定到不再存在的进程的搁浅作业。

相关问题