如何清除卡住/陈旧的 Resque 工作人员?

Posted

技术标签:

【中文标题】如何清除卡住/陈旧的 Resque 工作人员?【英文标题】:How do I clear stuck/stale Resque workers? 【发布时间】:2011-11-16 23:53:50 【问题描述】:

正如您从所附图片中看到的那样,我有几个工人似乎被困住了。这些过程不应超过几秒钟。

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

我在 Heroku 上使用 Resque 和 Redis-to-Go 和 HireFire 来自动扩展工作人员。

【问题讨论】:

嗨,半相关的问题:您是如何通过 heroku 获得 resque-web 仪表板的?我似乎无法弄清楚如何打开它。 【参考方案1】:

这些解决方案都不适合我,我仍然会在 redis-web 中看到:

0 out of 10 Workers Working

最后,这对我来说是清除所有工人的工作:

Resque.workers.each |w| w.unregister_worker

【讨论】:

这对我有用。它注销了 all 工人,这有点烦人。但这之后是heroku restart 似乎可以解决问题。它现在显示正确的工人数量。 这将工作人员从 Web 界面中取出,但实际上它们仍然显示为进程,并且还从队列中“窃取”了作业 如果您只想注销不是实际进程的工作人员(也可能是处理作业),您可能想尝试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 上运行良好。这可能仅在您的工作人员在您运行此代码的同一台机器上时才有效。 作为选项 Resque.workers.map &:unregister_worker 请注意,这不会摆脱工作进程。【参考方案2】:

在您的控制台中:

queue_name = "process_numbers"
Resque.redis.del "queue:#queue_name"

否则,您可以尝试将它们伪装成已完成删除它们,方法是:

Resque::Worker.working.each |w| w.done_working

编辑

很多人都支持这个答案,我觉得人们尝试使用 hagope 的解决方案很重要,该解决方案将工作人员从队列中注销,而上面的代码会删除队列。如果你乐于伪造它们,那就太酷了。

【讨论】:

如果他这样做会删除整个队列,他只是想删除卡住的那些.. 小更新:你现在必须使用 Resque.redis.del 而不是 Resque.redis.delete 现在实际上有一个 Resque.remove_queue() 方法【参考方案3】:

您可能已经安装了 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

【讨论】:

实际上,在第二次尝试时,这没有任何作用。 这非常适合清除那些在没有取消注册的情况下被杀掉的resque工人。 这似乎是新的最佳答案,因为它不会取消注册所有这些。 prune_dead_workers 不应该是一个类方法吗?但无论如何,很好的解决方案!谢谢。 这绝对是杀死 -9 工人的解决方案。我唯一要补充的是,您需要在使用 -9 杀死的同一台服务器上执行此操作。 一次性对所有人进行:Resque.workers.each(&:prune_dead_workers)【参考方案4】:

补充 hagope 的回答,我希望能够只注销已经运行了一段时间的工人。下面的代码只会取消注册运行超过 300 秒(5 分钟)的工作人员。

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

【讨论】:

显示如何通过 processing['run_at'] 访问作业开始时间的点。我见过使用 .started 方法的其他解决方案,但这实际上返回了 worker 启动的时间,而不是作业,这是清除卡住的工人的错误方法。谢谢!【参考方案5】:

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

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

您应该会看到如下内容:

92102 resque: Processing ProcessNumbers since 1253142769

记下我的示例中的 PID(进程 ID)它是 92102

然后您可以退出进程 1 of 2。

优雅地使用QUIT 92102

强制使用TERM 92102

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

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

【讨论】:

在 Linux 控制台中:kill -SIGQUIT 92102【参考方案6】:

我刚刚做了:

% rails c production
irb(main):001:0>Resque.workers

得到工人名单。

irb(main):002:0>Resque.remove_worker(Resque.workers[n].id)

... 其中 n 是不受欢迎的工人的从零开始的索引。

【讨论】:

【参考方案7】:

我有一个类似的问题,Redis 将数据库保存到包含无效(非运行)工作人员的磁盘。每次启动 Redis/resque 时,它​​们都会出现。

使用以下方法修复此问题:

Resque::Worker.working.each |w| w.done_working
Resque.redis.save # Save the DB to disk without ANY workers

确保重新启动 Redis 和 Resque 工作线程。

【讨论】:

【参考方案8】:

最近开始研究https://github.com/shaiguitar/resque_stuck_queue/。这不是解决卡住工人的解决方案,但它解决了重新挂起/被卡住的问题,所以我认为它可能对这个线程上的人有所帮助。来自自述文件:

“如果 resque 在特定时间范围内没有运行作业,它将触发您选择的预定义处理程序。您可以使用它来发送电子邮件、寻呼机任务、添加更多 resque 工作人员、重新启动 resque、发送给您一个 txt……随便你。”

已在生产中使用,到目前为止对我来说效果很好。

【讨论】:

【参考方案9】:

以下是如何通过主机名从 Redis 中清除它们。当我停用服务器并且工作人员没有正常退出时,就会发生这种情况。

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

【讨论】:

【参考方案10】:

我遇到了这个问题,并开始在此处实施许多建议。然而,我发现造成这个问题的根本原因是我是using the gem redis-rb 3.3.0。降级到 redis-rb 3.2.2 可以防止这些工作人员首先陷入困境。

【讨论】:

【参考方案11】:

我已经直接从 redis-cli 中清除了它们。幸运的是 redistogo.com 允许从 heroku 之外的环境进行访问。 从列表中获取死工人 ID。我的是

55ba6f3b-9287-4f81-987a-4e8ae7f51210:2

直接在redis中运行这个命令

del "resque:worker:55ba6f3b-9287-4f81-987a-4e8ae7f51210:2:*"

您可以监控 redis db 以查看它在幕后所做的事情。

redis xxx.redistogo.com> MONITOR
OK
1380274567.540613 "MONITOR"
1380274568.345198 "incrby" "resque:stat:processed" "1"
1380274568.346898 "incrby" "resque:stat:processed:c65c8e2b-555a-4a57-aaa6-477b27d6452d:2:*" "1"
1380274568.346920 "del" "resque:worker:c65c8e2b-555a-4a57-aaa6-477b27d6452d:2:*"
1380274568.348803 "smembers" "resque:queues"

倒数第二行删除worker。

【讨论】:

不是一个好主意。这不会在 Resque 中调用 unregister 钩子,不会调用失败和可能的清理代码。 这在 2 年前的 resque 中很有用,当时它显示了无法使用界面删除的卡住作业,并且在 rails 中没有干净的方法可以做到这一点【参考方案12】:

在 resque 2.0.0 中,似乎有一种方法可以在 resque 2.0.0 中仅移除实际上已死的工人:

Resque::Worker.all_workers_with_expired_heartbeats.each  |w| w.unregister_worker 

我不是这方面的专家,可能有更好的方法可以做到这一点,或者这会出现问题。我也只是想弄清楚这一点。

这似乎会从 resque 工作人员列表中删除未发送“心跳”的工作人员比预期的时间长得多。

如果幻影工作者处于“运行”状态,则将在“失败”作业队列中创建与幻影作业对应的新条目。

【讨论】:

【参考方案13】:

我在这里也有卡住/陈旧的 resque 工人,或者我应该说“工作”,因为工人实际上仍然在那里并且运行良好,这是卡住的分叉进程。

我选择了残酷的解决方案,即通过 bash 脚本杀死分叉进程“处理”超过 5 分钟,然后工作人员在队列中生成下一个,一切继续进行

在这里查看我的脚本:https://gist.github.com/jobwat/5712437

【讨论】:

【参考方案14】:

如果您使用的是较新版本的 Resque,则需要使用以下命令,因为内部 API 已更改...

Resque::WorkerRegistry.working.each |work| Resque::WorkerRegistry.remove(work.id)

【讨论】:

【参考方案15】:

只要您的 resque 版本比 1.26.0 更新,就可以避免该问题:

resque: env QUEUE=foo TERM_CHILD=1 bundle exec rake resque:work

请记住,它不会让当前正在运行的作业完成。

【讨论】:

【参考方案16】:

如果你使用 Docker,你也可以使用这个命令:

&lt;id&gt; 是工作人员 ID。

docker stop <id>

docker start <id>

【讨论】:

以上是关于如何清除卡住/陈旧的 Resque 工作人员?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不清除整个队列的情况下从 Resque 队列中删除特定作业?

如何使用 resque-web 监控 Coffee-resque 工作人员

如何在生产中部署 resque 工作者?

如何破坏由resque工人排队的工作?

Rails4:为啥 resque 工人不找工作

resque-web 作为独立的应用程序使用 rails api 监控工作人员