2011-09-21 80 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?它似乎沒有被主動維護,但可能會做你所需要的。

相關問題