Pourquoi Cacti continue d'attendre les processus de polling morts?

11

J'installe actuellement un nouveau serveur Debian (6.0.5). J'ai mis Cacti (0.8.7g) dessus hier et je me bats avec lui depuis.

Numéro initial

Le problème initial que j'observais était que mes graphiques ne se mettaient pas à jour. J'ai donc vérifié mon cacti.loget trouvé ce message concernant:

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

Ça ne peut pas être bon, non? J'ai donc vérifié et commencé poller.phpmoi-même (via sudo -u www-data php poller.php --force). Il va pomper beaucoup de messages (qui ressemblent tous à ce à quoi je m'attendrais) puis se bloquer pendant une minute. Après cette minute, il bouclera le message suivant:

Waiting on 1 of 1 pollers.

Cela continue pendant 4 minutes de plus jusqu'à ce que le processus soit forcé pour une durée supérieure à 298 s.

Jusqu'ici tout va bien

J'ai continué pendant une bonne heure à essayer de déterminer quel scrutateur pourrait encore fonctionner, jusqu'à ce que j'arrive à la conclusion qu'il n'y a tout simplement pas de scrutateur en cours d'exécution .

Débogage

J'ai vérifié poller.phpcomment cet avertissement est émis et pourquoi. À la ligne 368, Cacti récupérera le nombre de processus terminés de la base de données et utilisera cette valeur pour calculer le nombre de processus en cours d'exécution. Voyons donc cette valeur!

J'ai ajouté le code de débogage suivant dans 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";

Résultat

Cela imprimera ce qui suit dans une seconde après le démarrage poller.php:

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

Les valeurs sont donc en cours de lecture et sont valides. Jusqu'à ce que nous arrivions à la partie où il continue de boucler:

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

Soudain, la valeur a disparu. Pourquoi? La mise var_dump()en place confirme le problème:

NULL
Finished:  - Started: 1
Waiting on 1 of 1 pollers.

La valeur de retour est NULL. Comment est-ce possible lors d'une requête SELECT COUNT()...? ( SELECT COUNT()devrait toujours renvoyer une ligne de résultat, n'est-ce pas?)

Plus de débogage

Je suis donc allé lib\database.phpvoir ça db_fetch_cell(). Un peu de test a confirmé que l'ensemble de résultats est en fait vide.

J'ai donc ajouté mon propre code de requête de base de données pour voir ce que cela ferait:

$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 );

Cela produira

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

Ainsi, les données sont là et peuvent être consultées sans aucun problème, mais pas avec la méthode utilisée par Cacti?

Revérifiez cela!

J'ai activé la journalisation MySQL pour m'assurer que je n'imagine pas les choses. Effectivement, lorsque le message d'erreur est mis en boucle, le cacti.loglit comme s'il interrogeait comme un fou:

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'"

Mais aucune de ces requêtes n'est enregistrée par MySQL. Pourtant, lorsque j'ajoute mon propre code de requête de base de données, il s'affiche très bien.

entrez la description de l'image ici
Cliquez pour agrandir

Mais qu'est ce qu'il se passe ici?

Creuser plus profond...

J'ai conclu que la connexion à la base de données doit être perdue quelque part dans le processus et que adodb s'en fiche tout simplement.

Donc, après un peu de fouille, j'ai finalement placé le message de débogage drivers/adodb-mysql.inc.php, ligne 529, dans la _closefonction. Je voulais voir quand la connexion est fermée.

En fait, j'ai (enfin) activé le débogage PHP et j'ai réalisé qu'il mysql_query()était appelé avec un identifiant de connexion booléen (un indicateur d'une connexion intentionnellement fermée).

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

Qu'est-ce que cela imprime?

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

Et maintenant, je suis trop fatigué pour enquêter là-dessus ...

Der Hochstapler
la source

Réponses:

6

J'ai enquêté un peu plus loin et j'ai réalisé que la fermeture de la connexion à la base de données était intentionnelle. La connexion doit être rétablie pour le prochain cycle d'interrogation. Mais ce n'est pas le cas.

Voici un extrait de 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);
}

J'ai également vérifié db_connect_realet c'est, en fait, appelé après usleepachève. C'est donc là que je continuerai à creuser.

Pour l'instant, j'ai modifié la section comme ceci:

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);
}

Maintenant, le poller s'exécute sans aucun avertissement et mes graphiques sont dessinés. Pourtant, il y a toujours un problème. Tous mes graphiques ne sont pas dessinés correctement, comme le montre l'image suivante:

Un graphique rendu montrant les résultats de la solution de contournement
Cliquez pour agrandir

J'ai supposé que cela était dû au fait que le poller fonctionnait trop rarement pour certaines sources de données. Pour résoudre cela, je suis passé à la colonne vertébrale (ce que je voulais faire de toute façon) et l'ai configuré pour utiliser 4 threads.

Configuration du poller Cacti

Jusqu'ici tout va bien...

Mettre à jour

J'ai approfondi ce problème et j'ai pensé l'avoir résolu. J'ai supposé que la connexion n'était pas correctement stockée après la tentative de reconnexion du scrutateur.

Ma tentative de résoudre ce problème semblait prometteuse au début, mais les graphiques résultants étaient toujours défectueux. Le problème est donc plus profond.

La solution de contournement que j'ai développée plus tôt et présentée dans cette réponse fonctionne toujours parfaitement. J'ai décidé de ne plus investir de temps sur cette question et de rester avec la solution de contournement. Désolé.

Der Hochstapler
la source