我正在尝试监控monicorn的独角兽,所以当它们达到一定的内存阈值时,它会优雅地杀死它们。
问题:
当我告诉monit重新启动一个worker时,它首先尝试停止它,然后触发我的/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会识别出restart action is done
,然后注意到工作者PID已经改变并继续按预期监视该过程。
因此一切正常,monit能够在需要时重新启动工作人员并继续监视它们,但是日志中充满了错误,Web界面显示了令人讨厌(且令人困惑)的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,然后查看该进程是否存在。
然而,由于 kill-respawn worker操作发生得如此之快,monit没有意识到worker的pid已经改变并且一直等待(Bran new)worker死亡。然后它超时,然后它意识到pid实际上已经改变了,它正常。
我找到的肮脏解决方案:
为了证明这个假设,我试图减慢提到的 kill-respawn worker操作。因此,我编辑了unicorn配置文件,以便在他们在/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
它运作得非常好:鸟儿和鲜花在阳光灿烂的日子里唱歌,网络界面现在显示出良好的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
问题:
是否有实现此目的的 monit-way ?睡觉我的工人3秒似乎不是一个好的解决方案。有什么想法吗?
我明白这不是monit的正常情况。我们打破了monit的重启进程周期,因为我们不希望monit的start program
执行任何操作,而是让unicorn主进程处理它(如解释的那样)这里:http://www.stopdropandrew.com/2010/06/01/where-unicorns-go-to-die-watching-unicorn-workers-with-monit.html)
答案 0 :(得分: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信号关闭。