2013-03-05 55 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