如何清除卡住/过期的Resque工作者?

142

从附加的图片可以看出,有几个工人似乎卡住了。这些进程不应该需要超过几秒钟。

输入图像描述

我不确定它们为什么无法清除或者如何手动删除它们。

我正在使用 Heroku 上的 Resque ,其中包括 Redis-to-Go 和 HireFire 以自动扩展工作程序。


2
你好,半相关的问题:你是如何通过Heroku获取Resque-Web仪表板的?我似乎无法弄清楚如何打开它。 - Aaron Marks
16个回答

226

这些解决方案都对我没用,我仍然在redis-web中看到这个:

0 out of 10 Workers Working

最后,这个方法对我有效,可以清除所有的工作进程:

Resque.workers.each {|w| w.unregister_worker}

12
这对我很有效。它注销了所有的工人,有点烦人。但是接下来执行heroku restart似乎解决了问题。现在它显示了正确数量的工人。 - Brian Armstrong
这将工作人员从Web界面中移除,但实际上它们仍然显示为进程,并且从队列中“窃取”了工作。 - txwikinger
21
如果你只想注销不是实际进程(也许正在处理作业)的工作者,你可以尝试使用Resque.workers.each {|w| matches = w.id.match(/^[^:]*:([0-9]*):[^:]*$/); pid = matches[1]; w.unregister_worker unless w.worker_pids.include?(pid.to_s)}。这将仅注销那些pid不属于已知运行pid的工作者。我不知道这在所有环境中是否都有效,但在ubuntu上它表现良好。这可能仅在您的工作者位于运行此代码的同一台机器上时才有效。 - roychri
3
作为一个选项 Resque.workers.map &:unregister_worker - A B
1
请注意,这不会消除工作进程。 - Matheus Santana
显示剩余2条评论

54
在你的控制台中:
queue_name = "process_numbers"
Resque.redis.del "queue:#{queue_name}"
否则,你可以尝试伪造它们已经完成以移除它们,用如下方法:
Resque::Worker.working.each {|w| w.done_working}

编辑

很多人赞同这个答案,我认为让人们尝试hagope的解决方案很重要,该方案可以注销队列中的工作者,而上面的代码删除了队列。如果你愿意假装它们,那就很好。


3
如果他这样做,整个队列都会被删除,他只想移除卡住的那些。 - jBeas
1
小更新:现在您必须使用Resque.redis.del而不是Resque.redis.delete。 - James P McGrath
1
现在实际上有一个 Resque.remove_queue() 方法。 - iainbeeston

30

你可能已经安装了 resque gem,因此可以打开控制台并获取当前工作者

Resque.workers
它返回一个工人列表。
#=> [#<Worker infusion.local:40194-0:JAVA_DYNAMIC_QUEUES,index_migrator,converter,extractor>]

选择工作者并执行prune_dead_workers,例如第一个

Resque.workers.first.prune_dead_workers

1
实际上,第二次尝试时,这并没有做任何事情。 - Shpigford
2
这对于清除未注销的被杀死的Resque工作者非常有效。 - Lukas Eklund
3
这似乎是新的最佳答案,因为它不会注销所有内容。prune_dead_workers应该是一个类方法吗?但无论如何,这是一个很好的解决方案!谢谢。 - Brian Armstrong
这绝对是解决被 -9 杀死的进程的方法。唯一需要补充的是,你需要在同一台服务器上执行此操作,即你使用 -9 杀死进程的服务器。 - Stanislav O. Pogrebnyak
一次性对所有的工作进程执行操作:Resque.workers.each(&:prune_dead_workers) - Leo
在JAVA中是否有任何要添加的内容,以使工作人员不会陷入这种状态? - Arian Faurtosh

27

在hagope的答案基础上,我希望能够只注销已运行一定时间的worker。下面的代码只会注销运行超过300秒(5分钟)的worker。

Resque.workers.each {|w| w.unregister_worker if w.processing['run_at'] && Time.now - w.processing['run_at'].to_time > 300}

我有一个持续更新的Resque相关的Rake任务集合,并已将其添加到:https://gist.github.com/ewherrmann/8809350


3
显示如何通过 processing['run_at'] 访问作业的启动时间。我看到其他解决方案正在使用 .started 方法,但这实际上返回 工作者 启动的时间,而不是作业的时间,这是清除卡住的工作者的错误方法。谢谢! - Lachlan Cotter

10

在您运行启动服务器的命令的位置运行此命令

$ ps -e -o pid,command | grep [r]esque

你应该看到类似于这样的内容:

92102 resque: Processing ProcessNumbers since 1253142769

在我的例子中,记录PID(进程ID),它是92102

然后有两种方法可以退出进程1 0f 2。

  • 优雅地使用QUIT 92102

  • 强制性使用TERM 92102

* 我不确定语法是QUIT 92102还是QUIT -92102

如果你有任何问题,请告诉我。


3
在Linux控制台中: kill -SIGQUIT 92102该命令表示向进程号为92102的程序发送SIGQUIT信号,它将终止该进程并在终端上生成一个核心转储文件。 - Alexey

7
我刚刚做了以下事情:
% rails c production
irb(main):001:0>Resque.workers

获得了工人列表。
irb(main):002:0>Resque.remove_worker(Resque.workers[n].id)

...其中n是不需要的工人的零基索引。


2
我曾经遇到过类似的问题,Redis将包含无效(未运行)worker的DB保存到磁盘中。每次启动Redis/resque时,它们都会出现。
使用以下方法修复此问题:
Resque::Worker.working.each {|w| w.done_working}
Resque.redis.save # Save the DB to disk without ANY workers

请确保重新启动Redis和Resque工作者。


2

以下是如何根据主机名从Redis中清除它们的方法。当我停用服务器并且工作程序没有正常退出时,就会发生这种情况。

Resque.workers.each { |w| w.unregister_worker if w.id.start_with?(hostname) }

2
我遇到了这个问题,并开始实施这里提出的很多建议。然而,我发现导致这个问题的根本原因是我正在使用 gem redis-rb 3.3.0。将其降级为 redis-rb 3.2.2 可以防止这些工作线程一开始就被卡住。

2

最近开始着手处理https://github.com/shaiguitar/resque_stuck_queue/。它并不是解决工人卡住的方案,但它可以解决resque挂起/卡住的问题,因此我认为它可能对本主题中的人们有所帮助。从README中得知:

"如果resque在一定时间内没有运行作业,它将触发您选择的预定义处理程序。您可以使用此功能发送电子邮件、警报、添加更多的resque工作程序、重新启动resque、发送短信......任何适合您的方式。"

已经在生产中使用,并且对我来说效果相当不错。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接