3

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

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

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

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

4

4 回答 4

1
require 'timeout'
Timeout::timeout(60) do
  ...
end
于 2011-09-21T19:42:38.937 回答
1

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

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
于 2011-09-27T18:33:33.173 回答
0

事实证明,在一些示例 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
于 2011-09-27T18:01:46.893 回答
0

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

于 2014-01-29T00:38:48.443 回答