English

お問い合わせ

BLOG

続: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" が複数回出力されるようなこともあります。

関連記事

注意事項

サイバートラストのテレワークソリューション
採用情報ページ リニューアル
組込み Linux にプラスして 長期間の製品ライフサイクルをサポート EM+PLS