Browse Tag: httpd monit

monit で httpd を監視するときの tips

先日のエントリ「monit tips」で、httpd を監視する方法を変更したわけだが、先日ウェブサーバがメモリ不足になって落ちてしまった原因は次のとおりでだった。

  • Passenger を使っていると、かなりの高負荷のとき httpd を restart すると、httpd から fork している ruby のプロセスや ruby のプロセスを制御している ApplicationPool がちゃんと終了しない
  • そのため、ApplicationPool が複数起動して、AppliationPool から ruby のプロセスがたくさん起動した
  • その結果、メモリ不足となった
たしかに、ウェブサーバの負荷が高いときに apache を再起動してみると終了するのに数秒(3〜4秒くらい)かかる。
monit で restart の意味は monit 公式サイトのドキュメントに、次のような記載がある。
RESTART restarts the service and sends an alert. Restart is conducted by first calling the service’s registered stop method and then the service’s start method.
stop method を実行してから start method を実行するとなっている。stop method を実行してから、start method を実行するまでのウェイト時間を指定できないかなとドキュメントを読んでみたが、残念ながらそのような記載はなかった。
仕方がないので、monit 4.10.1 のソースコードで restart を実行する部分に焦点をあてて読んでみた。該当のソースコードは、control.c の次の部分だった。
case ACTION_RESTART:
if(s->type==TYPE_PROCESS && (!s->start || !s->stop)) {
DEBUG(“%s: Start or stop method not defined — process %s\n”, prog, S);
Util_monitorSet(s);
return;
}
LogInfo(“‘%s’ trying to restart\n”, s->name);
do_depend(s, ACTION_STOP);
if(do_stop(s)) {
/* Only start if stop succeeded */
do_start(s);
do_depend(s, ACTION_START);
} else {
/* enable monitoring of this service again to allow the restart retry
* in the next cycle up to timeout limit */
Util_monitorSet(s);
}
break;
do_stop 関数を呼んでから do_start 関数を実行している。それぞれの関数では、単純に設定ファイルで指定したプログラムを spawn 関数を呼んでいるだけだった。restart を指定する場合は、ウェイト時間を設定することができない。
monit は、なかなかきれいな C 言語のプログラムなので、ソースコードが読みやすいと思った。

対策を検討した結果、ヘルスチェックで失敗したときは httpd を終了させる専用のシェルスクリプトを実行するように変更することにした。こうすることで、ヘルスチェックに失敗すると、httpd を終了させて 60秒以内に httpd が起動していないので monit が自動的に httpd を起動してくれる。テストしたところで想定通りの動作をすることで、この設定でいくことにした。

check process httpd with pidfile /var/run/httpd.pid
start program = “/sbin/service httpd restart”
stop program = “/sbin/service httpd stop”
if failed host localhost port 80 protocol http
and request “/healthcheck/heartbeat”
for 3 cycles then exec “/home/hoge/bin/httpd_stop.sh”

この設定だと、/healthcheck/heartbeat で HTTP のステータスコード 200 以外に3回連続でなったとき、/home/hoge/bin/httpd_stop.sh を実行する。わざわざ終了するシェルスクリプトを用意したのは、Passenger のプロセスも含めてちゃんと終了するため。

ちなみに、/home/hoge/bin/httpd_stop.sh は、次のようになっている。

#!/bin/sh

if [ ! -f /var/run/httpd.pid ]; then
echo “httpd is not running”
exit 1
fi

service httpd stop

if [ -f /var/lock/subsys/httpd ]; then
rm -f /var/lock/subsys/httpd
fi

pkill -f ‘merb’
pkill -f ‘ApplicationPool’
ipcs -s | grep apache | awk ‘{print “sudo ipcrm -s “,$2}’ | sh

pkill しているのは、本番環境で使っている merb プロセスを落とすため。ApplicationPool も念のため kill する。最後に Apache のセマフォが使いきっていることがあるので、念のため入れておいた。

この設定で1週間くらい運用しているけれど問題ない様子。これで、メモリ不足になってリモートからサーバに接続できないこともなくなるだろう。

引き続き、httpd のヘルスチェックに失敗する原因を調査して、そもそも httpd が落ちないようにしよう。

monit tips -httpd-

monit を使って、httpd (Apache HTTP Server) のプロセスが落ちたときに自動的に再起動するようにしている。まれに httpd が落ちるときがあって、monit が httpd を再起動しようとしたとき次のようなログがでていてうまく再起動できない現状に遭遇した。

[JST Feb 10 01:13:59] error    : ‘httpd’ failed to start
[JST Feb 10 01:13:59] info     : ‘httpd’ trying to restart
[JST Feb 10 01:13:59] info     : ‘httpd’ start: /etc/init.d/httpd
[JST Feb 10 01:14:59] error    : ‘httpd’ process is not running
[JST Feb 10 01:14:59] info     : ‘httpd’ trying to restart
[JST Feb 10 01:14:59] info     : ‘httpd’ start: /etc/init.d/httpd
[JST Feb 10 01:14:59] error    : ‘httpd’ failed to start

 

よくよく調べてみると、一度 monit から httpd を起動したとき /var/lock/subsys/httpd ファイルや /var/run/httpd.pid ファイルが生成されない状態になって、monit が /var/run/httpd.pid がないので httpd が動いているのにも関わらず httpd を起動し続けていたことが原因。

/etc/init.d/httpd を修正しようと思ったが、monit の設定ファイルを次のように書き換えて対応したら、今のところは問題がない様子。

変更前

check process httpd with pidfile /var/run/httpd.pid
      start program = “/sbin/service httpd start”
      stop program = “/sbin/service httpd stop”
      if failed host localhost port 80 protocol http
         and request “/healthcheck/heartbeat”
         for 3 cycles then restart

変更後

check process httpd with pidfile /var/run/httpd.pid
start program = “/sbin/service httpd restart”
stop program = “/sbin/service httpd stop”
if failed host localhost port 80 protocol http
  and request “/healthcheck/heartbeat”
  for 3 cycles then restart
 

さて、次は httpd が落ちる原因を調査して対策することにしよう。