2011-09-21 82 views
3

我有一个神/ resque设置跨越几个工作服务器。每隔一段时间,工作人员就会被长时间的轮询连接堵塞,并且无法正常工作。我们试着围绕它进行编码(但不管它为什么不起作用),保持连接的数据包不会轻易地让它们发送出去。如何编写一个Resque条件,指出“如果一个进程运行时间超过n秒,杀死它”?

我希望某些工人(我已经在他们自己的手表块中已经分出)不允许超过一定的时间运行。在pesudocode,我正在寻找类似以下的手表状态(即如果它需要更长的时间超过60秒完成任务重新启动工人):如何做到这将大大

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

任何想法或指针赞赏。

回答

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 
1
require 'timeout' 
Timeout::timeout(60) do 
    ... 
end 
+0

您是否建议我在复古工人或上帝过渡/条件块中使用它?如果神t/c块,我将如何使用它?我的偏好是在上帝而不是在工人本身。 –

+1

使用超时宝石的这种解决方案不起作用。它不杀死线程。 –

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 
0

也许看看resque-restriction?它似乎没有被主动维护,但可能会做你所需要的。

相关问题