【问题标题】:How do I write a Resque condition that says "if a process is running for longer than n seconds, kill it"?如何编写一个 Resque 条件,上面写着“如果进程运行时间超过 n 秒,则终止它”?
【发布时间】:2025-12-05 20:10:01
【问题描述】:

我有一个跨越几个工作服务器的上帝/resque 设置。每隔一段时间,工作人员就会被长轮询连接卡住,并且不会正确超时。我们已经尝试围绕它进行编码(但不管它为什么不起作用),通过网络发送的保持活动数据包不会让我们轻易超时。

我希望某些工作人员(我已经在他们自己的监视块中分割出来)不允许运行超过一定时间。在伪代码中,我正在寻找类似以下的监视条件(即,如果完成任务的时间超过 60 秒,则重新启动该工作人员):

w.transition(:up, :restart) do |on|
  on.condition(:process_timer) do {|c|  c.greater_than = 60.seconds}
end

任何关于如何实现这一点的想法或指示将不胜感激。

【问题讨论】:

    标签: ruby resque god


    【解决方案1】:
    require 'timeout'
    Timeout::timeout(60) do
      ...
    end
    

    【讨论】:

    • 你是建议我在 resque worker 或 God 转换/条件块中使用它吗?如果上帝 t/c 块,我将如何使用它?我的偏好是在上帝而不是在工人本身中这样做。
    • 这种使用 Timeout gem 的解决方案不起作用。它不会杀死线程。
    【解决方案2】:

    虽然你有答案,我还是把它放在这里,因为我已经做到了:

    class TimedThread
      def initialize(limit, &block)
        @thread = Thread.new{ block.call }
        @start = Time.now
        Thread.new do
          while @thread.alive?
            if Time.now - @start > limit
              @thread.kill
              puts "Thread killed"
            end
          end
        end.join
      end
    end
    
    [1, 2, 3].each_with_index do |secs, i|
      TimedThread.new(2.5){ sleep secs ; puts "Finished with #{i+1}" }
    end
    

    【讨论】:

      【解决方案3】:

      事实证明,在一些示例 resque 文件中有一个如何执行此操作的示例。这不是我想要的,因为它没有添加 on.condition(:foo),但它是一个可行的解决方案:

      # This will ride alongside god and kill any rogue stale worker
      # processes. Their sacrifice is for the greater good.
      
      WORKER_TIMEOUT = 60 * 10 # 10 minutes
      
      Thread.new do
        loop do
          begin
            `ps -e -o pid,command | grep [r]esque`.split("\n").each do |line|
              parts   = line.split(' ')
              next if parts[-2] != "at"
              started = parts[-1].to_i
              elapsed = Time.now - Time.at(started)
      
              if elapsed >= WORKER_TIMEOUT
                ::Process.kill('USR1', parts[0].to_i)
              end
            end
          rescue
            # don't die because of stupid exceptions
            nil
          end
      
          # Sleep so we don't run too frequently
          sleep 30
        end
      end
      

      【讨论】:

        【解决方案4】:

        也许看看resque-restriction?它似乎没有处于主动维护状态,但可能会满足您的需求。

        【讨论】:

          最近更新 更多