Sidekiq如何停止一个正在运行的单个任务?

24

我需要以编程方式停止Sidekiq(3.1.2)中正在运行的作业,而不是预定的作业。我已经阅读了API文档,但并没有找到有关取消正在运行作业的信息。这是否可能使用Sidekiq实现?

如果直接不可能实现,则我的想法是在调用信号时在作业中引发异常,然后从重试集中删除该作业。虽然这显然不是最佳方法。

提前致谢。


1
那你是怎么解决这个问题的呢?能分享一下你的解决方法吗? - lazywei
看看第一个答案的常见问题解答,它非常清楚地解释了这个想法。我通过在执行操作时添加多个断点(即在每个块的开头)来做类似的事情。这基本上取决于您的用例,在何时/何处停止执行您的执行方法。 - Figedi
3个回答

15

请您能否详细说明一下?我不知道如何让一个作业自动停止。 - lazywei
1
哇,我实际上使用Redis和将所有jids存储在哈希中实现了与此版本类似的东西,然后在我的perform方法中添加断点,每次检查当前jid是否已设置在redis中。 - Figedi
有人建议在需要中断作业时杀死线程,您是否反对? - Henrique Zambon
4
如果那种方法是安全的,你难道不觉得Sidekiq会允许使用吗? - Mike Perham
看了上面的链接,我认为一旦我们调用setex函数,作业的状态就会被设置为“已取消”,并停止执行。现在,当这个作业再次尝试运行时,那么return if cancelled?部分有效地完成/结束了作业。这是正确的解释吗?@MikePerham - Masroor

6

如果您知道长时间运行的作业的线程ID,则可以从另一个任务终止它:

class ThreadLightly
  include Sidekiq::Worker

  def perform(tid)
    puts "I'm %s, and I'll be terminating TID: %s..." % [self.class, tid]
    Thread.list.each {|t|
      if t.object_id.to_s == tid
        puts "Goodbye %s!" % t
        t.exit
      end
    }
  end
end

你可以从 sidekiq_pusher 触发它:
bundle exec ./pusher.rb ThreadLightly $YOURJOBSTHREADID

您需要记录每个作业的Thread.current.object_id,因为UI不会显示它。此外,如果您运行分布式sidekiqs,则需要运行此任务,直到它在同一实例上运行。


正是我所需要的!只有一个小修正:此时(2017年),您应该使用 object_id.to_s(36) - sigra
如果您的Sidekiq运行在多个实例上,我不确定这种方法是否有效。如果您想要终止的作业在A实例上,但是该工作程序在B实例上执行,会发生什么情况?据我所知,您无法知道将分配给哪个进程此工作程序。 - gmm

3

使用 Sidekiq 仪表盘。

停止正在运行的作业的另一种方法是停止 Sidekiq 进程。

enter image description here

并且停止Sidekiq进程需要一些时间。 如果Sidekiq进程停止,所有正在运行的作业将被重新定位到enqued部分。因此,如果您重新启动Sidekiq进程,它将再次运行。

您需要删除所有在enqued部分的作业。您可以使用仪表板来完成,或者在Rails控制台上运行以下命令。

## queue_name = 'logger'
## Sidekiq::Queue.new(queue_name).each { |e| e.delete }

# e.g.
Sidekiq::Queue.new('logger').each { |e| e.delete }

或者... 使用仪表盘...

enter image description here

enter image description here

它将从所有作业队列中移除。 现在您可以重新启动您的Sidekiq进程。


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