我正在尝试用 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
,然后注意到 worker 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 已经改变并一直在等待(全新的)worker 死亡。然后它超时,然后它意识到pid实际上已经改变并且它正常运行。
我发现的肮脏解决方案:
为了证明这个假设,我试图减慢提到的kill-respawn worker 操作。所以我编辑了 unicorn 配置文件,让新工作人员在/tmp/unicorn.orly.0.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
问题:
有没有实现这一目标的监控方式?让我的工人睡 3 秒钟似乎不是一个好的解决方案。有任何想法吗?
我知道这不是 monit 的正常情况。我们打破了monit的重启过程循环,因为我们不希望start program
monit执行任何操作,而是让独角兽主进程处理它(如这里解释:http: //www.stopdropandrew.com/ 2010/06/01/where-unicorns-go-to-die-watching-unicorn-workers-with-monit.html )