web-dev-qa-db-ja.com

Cactiがデッドポーラープロセスを待機し続けるのはなぜですか?

現在、新しいDebian(6.0.5)サーバーをセットアップしています。私は昨日サボテン(0.8.7g)を入れて以来、ずっと戦っています。

新規作成

私が観察していた最初の問題は、グラフが更新されないことでした。だから私は_cacti.log_を確認し、これに関するメッセージを見つけました:

_POLLER: Poller[0] Maximum runtime of 298 seconds exceeded. Exiting.
_

それは良くありませんね?それで私はチェックしに行きました _poller.php_ 私自身(_Sudo -u www-data php poller.php --force_を介して)。それは多くのメッセージ(すべて私が期待するもののように見えます)を送り出してから、1分間ハングします。その1分後、次のメッセージがループします。

_Waiting on 1 of 1 pollers.
_

これは、プロセスが強制的に終了して298秒より長く実行されるまで、さらに4分間続きます。

ここまでは順調ですね

まだ実行中のポーラーを特定するために良い時間を費やしましたが、実行中のポーラーがないだけであるという結論に至るまで

デバッグ中

_poller.php_ をチェックして、その警告がどのように発行され、その理由を確認しました。 368行目で、Cactiはデータベースから終了したプロセスの数を取得し、その値を使用して、まだ実行されているプロセスの数を計算します。だから、その値を見てみましょう!

次のデバッグコードを _poller.php_ に追加しました。

_$finished_processes = db_fetch_cell("SELECT count(*) FROM cacti.poller_time WHERE poller_id=0 AND end_time>'0000-00-00 00:00:00'");
print "Finished: " . $finished_processes . " - Started: " . $started_processes . "\n";
_

結果

これにより、_poller.php_を開始してから1秒以内に以下が出力されます。

_Finished: 0 - Started: 1
Waiting on 1 of 1 pollers.
Finished: 1 - Started: 1
_

したがって、値は読み取られており、有効です。 Untilループが続く部分に到達します:

_Finished:  - Started: 1
Waiting on 1 of 1 pollers.
_

突然、その価値はなくなります。どうして? var_dump()をそこに置くと、問題が確認されます:

_NULL
Finished:  - Started: 1
Waiting on 1 of 1 pollers.
_

戻り値はNULLです。 SELECT COUNT()...をクエリするとどうなりますか? (SELECT COUNT()は常に1つの結果行を返す必要がありますね。)

より多くのデバッグ

それで、私は _lib\database.php_ に入り、db_fetch_cell()を調べました。テストの結果、結果セットは実際には空であることが確認されました。

そこで、自分のデータベースクエリコードを追加して、それがどうなるかを確認しました。

_$finished_processes = db_fetch_cell("SELECT count(*) FROM poller_time WHERE poller_id=0 AND end_time>'0000-00-00 00:00:00'");
print "Finished: " . $finished_processes . " - Started: " . $started_processes . "\n";

$mysqli = new mysqli("localhost","cacti","cacti","cacti");
$result = $mysqli->query("SELECT COUNT(*) FROM poller_time WHERE poller_id=0 AND end_time>'0000-00-00 00:00:00';");
$row = $result->fetch_assoc();
var_dump( $row );
_

これは出力されます

_Finished:  - Started: 1
array(1) {
  ["COUNT(*)"]=>
  string(1) "2"
}
Waiting on 1 of 1 pollers.
_

それで、データはそこにあり、Cactiが使用している方法ではなく、問題なくアクセスできますか?

それを再確認してください!

私はMySQLロギングを有効にして、私が物事を想像していないことを確認しました。案の定、エラーメッセージがループしている場合、_cacti.log_は、madのようにクエリを実行しているかのように読み取ります。

_06/29/2012 08:44:00 PM - CMDPHP: Poller[0] DEVEL: SQL Cell: "SELECT count(*) FROM cacti.poller_time WHERE poller_id=0 AND end_time>'0000-00-00 00:00:00'"
06/29/2012 08:44:01 PM - CMDPHP: Poller[0] DEVEL: SQL Cell: "SELECT count(*) FROM cacti.poller_time WHERE poller_id=0 AND end_time>'0000-00-00 00:00:00'"
06/29/2012 08:44:02 PM - CMDPHP: Poller[0] DEVEL: SQL Cell: "SELECT count(*) FROM cacti.poller_time WHERE poller_id=0 AND end_time>'0000-00-00 00:00:00'"
_

ただし、これらのクエリのnoneはMySQLによって記録されます。それでも、自分のデータベースクエリコードを追加すると、問題なく表示されます。

enter image description here
拡大するにはクリックしてください

ここで一体何が起こっているのですか?

深く掘り下げています...

データベース接続はプロセスのどこかで失われる必要があり、adodbは単に気にしないと結論付けました。

少し調べた後、デバッグメッセージを_drivers/adodb-mysql.inc.php_関数の__close_、529行目に配置しました。接続がいつ閉じられるかを確認したいと思いました。

私は実際に(最終的に)オンにしましたPHPデバッグし、mysql_query()がブール接続ID(意図的に閉じられた接続のインジケーター)で呼び出されたことを認識しました。

_// returns true or false
function _close()
{
    @mysql_close($this->_connectionID);
    echo "!!!! CLOSED !!!!\n";
    debug_print_backtrace();
    $this->_connectionID = false;
}
_

それは何を印刷しますか?

_oliver@j27773:/etc/php5/conf.d$ Sudo -u www-data php /usr/share/cacti/site/poller.php --force
06/30/2012 01:33:49 AM - POLLER: Poller[0] NOTE: Poller Int: '60', Cron Int: '300', Time Since Last: '61', Max Runtime '298', Poller Runs: '5'
06/30/2012 01:33:49 AM - POLLER: Poller[0] DEBUG: About to Spawn a Remote Process [CMD: /usr/bin/php, ARGS: -q "/usr/share/cacti/site/cmd.php" 0 3]
Finished: 0 - Started: 1
Waiting on 1 of 1 pollers.
Finished: 1 - Started: 1
06/30/2012 01:33:50 AM - POLLER: Poller[0] CACTI2RRD: /usr/bin/rrdtool update /var/lib/cacti/rra/j27773_servers_jiffybox_net_Apache_sb_keepalive_100.rrd --template Apache_sb_keepalive 1341012829:0
06/30/2012 01:33:50 AM - POLLER: Poller[0] CACTI2RRD: /usr/bin/rrdtool update /var/lib/cacti/rra/j27773_servers_jiffybox_net_Apache_reqpersec_95.rrd --template Apache_reqpersec 1341012829:.0228409
06/30/2012 01:33:50 AM - POLLER: Poller[0] CACTI2RRD: /usr/bin/rrdtool update /var/lib/cacti/rra/j27773_servers_jiffybox_net_Apache_bytesperreq_90.rrd --template Apache_bytesperreq 1341012829:13925.7
06/30/2012 01:33:50 AM - POLLER: Poller[0] CACTI2RRD: /usr/bin/rrdtool update /var/lib/cacti/rra/j27773_servers_jiffybox_net_cpu_85.rrd --template cpu 1341012829:1
OK u:0.00 s:0.00 r:1.00
06/30/2012 01:33:50 AM - POLLER: Poller[0] CACTI2RRD: /usr/bin/rrdtool update /var/lib/cacti/rra/j27773_servers_jiffybox_net_hdd_used_80.rrd --template hdd_used:hdd_total 1341012829:924741632:2677886976
OK u:0.00 s:0.00 r:1.00
OK u:0.00 s:0.01 r:1.00
OK u:0.00 s:0.01 r:1.00
06/30/2012 01:33:50 AM - POLLER: Poller[0] CACTI2RRD: /usr/bin/rrdtool update /var/lib/cacti/rra/j27773_servers_jiffybox_net_Apache_sb_wait_105.rrd --template Apache_sb_wait 1341012829:9
OK u:0.00 s:0.01 r:1.00
OK u:0.00 s:0.01 r:1.00
06/30/2012 01:33:50 AM - SYSTEM STATS: Time:1.1261 Method:cmd.php Processes:1 Threads:N/A Hosts:2 HostsPerProcess:2 DataSources:7 RRDsProcessed:6
Loop  Time is: 1.1291718482971
Sleep Time is: 58.867464065552
Total Time is: 1.1325359344482
!!!! CLOSED !!!!
#0  ADODB_mysql->_close() called at [/usr/share/php/adodb/adodb.inc.php:2141]
#1  ADOConnection->Close() called at [/usr/share/cacti/site/lib/database.php:68]
#2  db_close() called at [/usr/share/cacti/site/poller.php:455]
^C06/30/2012 01:33:55 AM - CMDPHP: Poller[0] WARNING: Cacti Master Poller process terminated by user
_

そして今、私はそれを調査するのに疲れすぎています...

11
Der Hochstapler

私はもう少し調査しましたが、データベースへの接続を閉じることは意図的なものであることに気付きました。接続は、次のポーリング実行のために再確立する必要があります。しかし、そうではありません。

これはpoller.phpからの抜粋です。

if ($poller_runs_completed < $poller_runs) {
    db_close();
    // Debug message by myself
    echo "RECONNECTING IN " . $sleep_time . "\n";
    usleep($sleep_time * 1000000);
    db_connect_real($database_hostname, $database_username, $database_password, $database_default, $database_type, $database_port);
}

db_connect_realもチェックしましたが、実際にはusleepの完了後に呼び出されます。だから私は掘り続けます。

とりあえず、このセクションを次のように変更しました。

if ($poller_runs_completed < $poller_runs) {
    //db_close();
    // Debug message by myself
    echo "RECONNECTING IN " . $sleep_time . "\n";
    usleep($sleep_time * 1000000);
    //db_connect_real($database_hostname, $database_username, $database_password, $database_default, $database_type, $database_port);
}

これでポーラーは警告なしで実行され、グラフが描画されます。しかし、まだ問題があります。次の画像からわかるように、すべてのグラフが適切に描画されているわけではありません。

A rendered graph showing the results from the workaround
拡大するにはクリックしてください

これは、特定のデータソースではポーラーがほとんど実行されないことが原因であると思いました。それを解決するために、私は spine (とにかくやりたかった)に切り替えて、4つのスレッドを使用するように設定しました。

Cacti poller configuration

ここまでは順調ですね...

更新

私はこの問題をより深く掘り下げ、修正したと思いました。ポーラーの再接続試行後、接続が適切に保存されていないと想定しました。

それを解決する私の試みは最初は有望に見えましたが、結果のグラフはまだ不完全でした。したがって、問題はより深いところにあります。

以前に開発し、この回答で示した回避策はまだ完全に機能します。私はこの問題にこれ以上の時間を投資せず、回避策を続けることにしました。ごめんなさい。

6
Der Hochstapler