私は 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 は必要に応じてワーカーを再起動し、監視を続けることができますが、ログにはエラーがいっぱいで、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 操作は非常に高速に行われるため、monit はワーカーの pid が変更されたことを認識せず、(新しい) ワーカーが終了するのを待ち続けます。その後、タイムアウトになり、pidが実際に変更されたことに気づき、通常どおりになります。
私が見つけた汚い解決策:
この仮説を証明するために、前述のkill-respawn ワーカー操作を遅くしようとしました。そこで、ユニコーンの設定ファイルを編集して、新しい pid を書き留める直前に、新しいワーカーを数秒間スリープさせました/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
そして、見事に機能しました。晴れた日には鳥や花が歌い、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
質問:
これを達成する方法はありますか?ワーカーを 3 秒間スリープ状態にすることは、良い解決策とは思えません。何か案は?
これはmonitの通常の状況ではないことを理解しています。monit にアクションを実行させたくないので、monitの再起動プロセス サイクルを壊しましたstart program
が、代わりにユニコーン マスター プロセスに処理させます (ここで説明されているように: http://www.stopdropandrew.com/ 2010/06/01/where-unicorns-go-to-die-watching-unicorn-workers-with-monit.html )