キャッシュが破棄されている… 【MIRACLE ZBX 2.0, 2.2】
検証を行っていますが、シャットダウン時にアイテムの情報がシンクされていない!
という、結構問題のある質問を当社のサポート宛に頂きました。
実際に再現テストをしていくと、何故か最新のバージョン(Zabbix 2.2.10)では再現します。同様に2.0.15でも再現しますが、1.8.22では再現しません。でも、以前2.0.8ぐらいで同じようなテストをしたときには、問題なかったのにな~と思いつつ、いろいろと調査です。
キャッシュからDBへのシンクの仕組み
何度か説明をしていますが、シャットダウンのことも踏まえ、キャッシュからDBへのシンクの仕組みを説明します。
PollerプロセスやTrapperプロセスが監視データを受け取った後に、共有メモリ上のヒストリキャッシュへ保存を行い、DBへは直接書き込みをしないようになっています。
その後、複数のDB Syncerプロセスが定期的にキャッシュからDBへの書き出しを行います。この一連の書き出しの処理の中で、トリガー評価などを行います。
ただし、上記の書き出し処理は通常の場合です。
Zabbix Serverのシャットダウン処理
次にシャットダウン処理の説明です。シャットダウンの方法もいくつかありますが、最も安全である方法で説明します。
ユーザがZabbix Serverサービスをシャットダウンするにあたって、SIGTERM等のシグナルをZabbix Serverの親プロセスに投げます。
SIGTERMシグナルを受け取った親プロセスは、全ての子プロセスにSIGTERMプロセスを投げ、全ての子プロセスが終了するまで待ちます。その後、ヒストリキャッシュのシンク処理をした後に終了します。
これにより、データの消失はありません。
ソースコードは問題なさそうなのだけど…
以前、調べたソースとちょっと違うな~と思いつつ読んでみたけど、問題なさそうです。
で、デバッグコードを入れつつ、調査していくと、何かロック関係でサクッと処理をせずに抜けていることが判明しました。DCconfig_lock_triggers_by_itemids()、DCconfig_unlock_triggers()という関数が追加され、トリガーにロックステータスを保持するようになっています。
結局のところ、現象としては下記となります。
- DB Syncerがシンク処理を開始。シンクするアイテムに関するトリガーのロックを取得する。
- 親プロセスがSIGTERMシグナルを受け取り、全ての子プロセスにSIGTERMを送る。
- シンク処理していたDB SyncerプロセスがSIGTERMを受け取り、終了する。このとき、ロックのリリースを行わない。
- 親プロセスがシンク処理を開始する。しかし、ロックが取得できないため、シンクをしないアイテムがある。
既に、報告はしているのでそのうちに取り込まれると思います。MIRACLE ZBXでは時期リリースパッケージ(多分2.2.11-1, 2.0.16-1)にて修正する予定です。
2015/12/22追記 本家では2.0.17, 2.2.12, 3.0.0にて取り込まれます。