BLOG
2019 年 01 月 22 日
続:Zabbix / MIRACLE ZBX ServerのPollerプロセスのエラー処理
ネットワークエラーが発生した際に、監視が遅延することががよくあります。本来のタイミングから数十分遅れたというケースもあります。監視が遅延する原因は何でしょうか?Poller と Unreachable Poller プロセスがネットワークエラーをどう処理しているかに注目して解説します。
Poller プロセスと Unreachable Poller プロセス
Poller プロセスはパッシブ系のアイテムの監視を処理するプロセスであり、Unreachable Poller はその処理においてネットワークエラーとなったアイテムを処理するプロセスです。
ネットワークエラーが発生した場合、エラーとなったアイテムが属するホスト上の同じタイプの全てのアイテムが Poller プロセスの監視キューから、Unreachable Poller プロセスの監視キューに移行されます。
エラーが発生したアイテムのタイプが Zabbix エージェントなら、そのアイテムが登録されているホストのタイプが Zabbix エージェントである全てのアイテムが移行の対象となります。

最悪の場合、本来 Poller プロセスが処理する全てのアイテムが Unreachable Poller プロセスに割り当てられます。Unreachable Poller の処理能力を上回るような処理が割り当てられれば、処理しきれずに監視が遅延してしまいます。多くの場合これが原因です。
一般的に、Unreachable Poller の数は Poller プロセスの数よりも少なく設定されます。Poller プロセスのデフォルト値は 5 であるのに対して、Unreachable Poller プロセスのデフォルト値は 1 です。Unreachable Poller プロセスの数は少なくしすぎないように注意しましょう。
処理の実装
では、上記に関する処理がどのように実装されているかを見ていきます。
監視データを取得する際にネットワークエラーが発生すると、deactivate_host() がコールされます。この関数は、フラグ (errors_from,disable_until,available) の値を変更して、該当するエラーを出力します。
src/zabbix_server/poller/poller.c
346 static void deactivate_host(DC_ITEM *item, zbx_timespec_t *ts, const char *error)
347 {
...
364 if (FAIL == DChost_deactivate(item->host.hostid, agent_type, ts, &in.agents[agent_type],
365 &out.agents[agent_type], error))
366 {
367 goto out;
368 }
370 if (FAIL == db_host_update_availability(&out))
371 goto out;
372
373 if (0 == in.agents[agent_type].errors_from)
374 {
375 zabbix_log(LOG_LEVEL_WARNING, "%s item \"%s\" on host \"%s\" failed:"
376 " first network error, wait for %d seconds",
377 zbx_agent_type_string(item->type), item->key_orig, item->host.host,
378 out.agents[agent_type].disable_until - ts->sec);
379 }
380 else
381 {
382 if (HOST_AVAILABLE_FALSE != in.agents[agent_type].available)
383 {
384 if (HOST_AVAILABLE_FALSE != out.agents[agent_type].available)
385 {
386 zabbix_log(LOG_LEVEL_WARNING, "%s item \"%s\" on host \"%s\" failed:"
387 " another network error, wait for %d seconds",
388 zbx_agent_type_string(item->type), item->key_orig, item->host.host,
389 out.agents[agent_type].disable_until - ts->sec);
390 }
391 else
392 {
393 zabbix_log(LOG_LEVEL_WARNING, "temporarily disabling %s checks on host \"%s\":"
394 " host unavailable",
395 zbx_agent_type_string(item->type), item->host.host);
396
397 update_triggers_status_to_unknown(item->host.hostid, item->type, ts,
398 "Agent is unavailable.");
399 }
400 }
401 }
各ホスト毎のある構造体のメンバーの変数である errors_from,disableuntil,available が関連のフラグとなっています。それらの変数は、DB のテーブル hosts の同名のカラムに対応しています。フラグの値の変更は l.364 の DChost_deactivate() において行われます。
各々のフラグについて解説します。
- "errors_from" には継続せず発生したネットワークエラーの発生時刻が入ります。初期値が 0 であり、監視が成功すれば別の関数で 0 がセットされます。つまり、ネットワークエラーが発生した際にこの値が 0 ならば、そのネットワークエラーが継続せず発生したことになります。この場合、ログ "first network error ..." を出力します。
- "disable_until" はネットワークエラーが発生した際に、次回の監視時刻を記録する変数であり、継続せず発生したネットワークエラーの発生時刻に UnreachableDelay を加えた時刻が入ります。初期値が 0 であり、監視が成功すれば別の関数で 0 がセットされます。この変数は Unreachable Poller の監視キューに移行するかを判定するフラグとしても使用されます。
- "available" はホストの状態 (unavailable/available) を格納する変数です。ネットワークエラーが発生した際に、errors_from か UnreachablePeriod(zabbix_server.conf) に設定した値以上が経過してしていれば、HOST_AVAILABLE_FALSE がセットされます。
(l.382,l.384) 監視を行う前と後の "available" の値が HOST_AVAILABLE_FALSE でない場合、"another network error..." のログを出力します。これは、継続してネットワークエラーが発生して、エラーが発生してから UnreachablePeriod が経過してない場合に該当します。
(l.391) 監視を行う際の "avaiable" が HOST_AVAILABLE_FALSE である場合の処理です。この場合、"temporarily disabling ..." のログを出力します。これは、継続せず発生したネットワークエラーの発生時刻から UnreachablePeriod が経過して、ホストが unavailable にセットされた場合に該当します。
Unreachable Poller の監視キューにアイテムを移行する処理
アイテムを別の監視キューに移行する処理は、監視データの取得が終わったアイテムを監視キューにセットする処理と、自身の監視キューから監視するアイテムのデータを取得する処理において行われます。
自身の監視キューから監視するアイテムのデータを取得する処理を確認します。
処理は DCconfig_get_poller_items() において行われます。
src/libs/zbxdbcache/dbconfig.c
5737 int DCconfig_get_poller_items(unsigned char poller_type, DC_ITEM *items)
5738 {
...
5764 while (num < max_items && FAIL == zbx_binary_heap_empty(queue))
5765 {
...
5814 if (0 == (disable_until = DCget_disable_until(dc_item, dc_host)))
5815 {
...
5829 }
5830 else
5831 {
5832 if (ZBX_POLLER_TYPE_NORMAL == poller_type ||
5833 ZBX_POLLER_TYPE_IPMI == poller_type ||
5834 ZBX_POLLER_TYPE_JAVA == poller_type)
5835 {
5836 old_poller_type = dc_item->poller_type;
5837 dc_item->poller_type = ZBX_POLLER_TYPE_UNREACHABLE;
5838
5839 old_nextcheck = dc_item->nextcheck;
5840 if (disable_until > now)
5841 dc_item->nextcheck = DCget_unreachable_nextcheck(dc_item, dc_host);
5842
5843 DCupdate_item_queue(dc_item, old_poller_type, old_nextcheck);
5844 continue;
5845 }
...
5856 }
...
5877 }
5878
5883 return num;
5884 }
(l.5814) において、取得したアイテムのあるホストのフラグ "disable_until" が 0 であるかの判定を行っています。上述のとおり、"disable_until" ネットワークエラーが発生した際に次回監視を行う時刻がセットされます。これにより、ネットワークエラーが発生しているとみなされ、 Poller プロセスでは監視は行わず、Unreachable Poller プロセスの監視キューに移行されます。
(l.5837) アイテムを処理する Poller プロセスのタイプを通常の Poller から、Unreachable Poller に変更し、(l.5843)DCupdate_item_queue() において、現在の通常の Poller プロセスの監視キューからの削除と、移行先の Unreachable Poller プロセスの監視キューへの追加を行っています。
以上、ネットワークエラー発生時の処理について解説を行いました。
なお、解説では説明のためにシナリオを簡略化してます。Zabbix エージェントタイプのアイテムのみを想定しています。また、Poller/Unreachable Poller は共に 1 プロセスであることを想定しています。実際には Poller プロセスは複数個の同時に並行して動作していることから、タイミングによっては、"first network error" が複数回出力されるようなこともあります。
関連記事
注意事項
- 本ドキュメントの内容は、予告なしに変更される場合があります。
- 本ドキュメントは、限られた評価環境における検証結果をもとに作成しており、全ての環境での動作を保証するものではありません。
- 本ドキュメントの内容に基づき、導入、設定、運用を行なったことにより損害が生じた場合でも、当社はその損害についての責任を負いません。あくまでお客さまのご判断にてご使用ください。












