2013-03-05 49 views
2

我試圖監視麒麟工人monit,所以它優雅地殺死他們,當他們達到一定的內存門檻。Monit超時停止麒麟工人,如果他們重生太快

問題:

當我告訴monit的重新啓動它首先試圖阻止它,我的射擊腳本/etc/init.d/unicorn kill_worker 0命令工人。

# my /etc/monit/config.d/unicorn file 
check process orly_unicorn_worker_0 with pidfile /tmp/unicorn.orly.0.pid 
    start program = "/bin/true" 
    stop program = "/etc/init.d/unicorn_orly kill_worker 0" 

由於我通過top命令我看到工人是如何死亡,如何掌握產卵用的,當然,另一個PID一個新的工作監測過程。

但是,Monit會等待一段時間,並在其日誌中引發「未能停止」錯誤。它實際上等待30秒並超時。

一旦超時,monit識別restart action is done,然後通知工作人員PID已更改,並繼續按預期監視該過程。因此一切正常,monit能夠在需要的時候重新啓動一個worker,並持續監視它們,但是日誌中充滿了錯誤,web界面在worker上顯示了一個令人討厭的(令人困惑的)execution failed錯誤狀態,我想如果他們成立了,它會發送錯誤的電子郵件提醒。

這是日誌的相關部分,當我試圖重新啓動通過Web界面工人(注意如何它還獲取與工人父PID混淆):

[UTC Mar 5 13:29:17] info  : 'orly_unicorn_worker_0' trying to restart 
[UTC Mar 5 13:29:17] info  : 'orly_unicorn_worker_0' stop: /etc/init.d/unicorn_orly 
[UTC Mar 5 13:29:47] error : 'orly_unicorn_worker_0' failed to stop 
[UTC Mar 5 13:29:47] info  : 'orly_unicorn_worker_0' restart action done 
[UTC Mar 5 13:29:47] error : 'orly_unicorn_worker_0' process PID changed to 13699 
[UTC Mar 5 13:29:49] error : 'orly_unicorn_worker_0' process PPID changed to 0 
[UTC Mar 5 13:30:19] info  : 'orly_unicorn_worker_0' process PID has not changed since last cycle 
[UTC Mar 5 13:30:19] error : 'orly_unicorn_worker_0' process PPID changed to 13660 
[UTC Mar 5 13:30:49] info  : 'orly_unicorn_worker_0' process PPID has not changed since last cycle 

這花了我很長但是,這裏發生的事情是,工人被殺死,然後迅速重生,monit甚至沒有注意到這一變化。

我的猜測是,monit在執行停止操作時會讀取/tmp/unicorn.orly.0.pid以獲取進程的pid,然後查看該進程是否存在。

但是,由於殺死重生工作人員操作發生得如此之快,monit並沒有意識到工人的PID已經改變並且一直等待(麩皮新)工人死亡。然後它超時,然後它意識到pid實際上已經改變,並且正常進行。

骯髒的解決方案,我發現:

爲了證明這一假設我想提到的殺 - 重生工人操作放緩。所以我編輯了獨角獸配置文件​​,讓他們在/tmp/unicorn.orly.0.pid寫下新pid之前幾秒鐘讓新員工入睡。

我做了這樣的:

after_fork do |server, worker| 
    sleep 3 

    # write down the new worker PID so monit can monitor it 
    child_pid = server.config[:pid].sub(".pid", ".#{worker.nr}.pid") 
    system("echo #{Process.pid} > #{child_pid}") 
end 

它表現的很出色:花鳥在晴天唱歌,Web界面現在顯示一個不錯process running狀態,日誌顯示一切都很順利,需要看:

[UTC Mar 5 13:30:44] info  : 'orly_unicorn_worker_0' trying to restart 
[UTC Mar 5 13:30:44] info  : 'orly_unicorn_worker_0' stop: /etc/init.d/unicorn_orly 
[UTC Mar 5 13:30:45] info  : 'orly_unicorn_worker_0' stopped 
[UTC Mar 5 13:30:45] info  : 'orly_unicorn_worker_0' start: /bin/true 
[UTC Mar 5 13:30:46] info  : 'orly_unicorn_worker_0' restart action done 

問題:

是否有莫nit-way的實現?睡3秒我的工人似乎不是一個好的解決方案。有任何想法嗎?

我知道這不是monit的正常情況。我們那種打破了重啓過程週期的monit的,因爲我們不希望的monit的start program不執行任何操作,而是讓麒麟主進程處理它(如下解釋:)

+0

從那以後你找到了解決方案嗎?我也認爲'睡覺3'是古怪的。 – kenn 2014-01-24 03:13:34

回答

0

在我們的環境,monit監視麒麟主人,麒麟主人監督其子女。我們用一個簡單的cron來監測麒麟工人,殺死他們,如果超過了內存閾值:

#!/usr/bin/env ruby 
    #  

    def get_mem(pid) 
     pid = pid.to_i 
     mem = 0 
     if File.exist?("/proc/#{pid}/status") 
     File.read("/proc/#{pid}/status").each_line do |status| 
      next unless status =~ /^VmRSS:\s+(\d+) kb/i 
      mem = $1.to_i/1024 
     end  
     end  
     mem  
    end  

    %x{pgrep -f 'unicorn worker'}.each_line do |pid| 
     Process.kill('QUIT', pid.to_i) if (get_mem pid) >= 300 
    end 

麒麟主通知書時,孩子已經被殺害,並自動重生一個新的。我很確定獨角獸工作人員在當前請求完成後將關閉QUIT信號。

+0

不是我一直在尋找的答案,但似乎是一個值得考慮的選擇。非常感謝你的貢獻,約翰;) – ariera 2013-03-07 23:45:57