Créer un service pour fermer les connexions persistantes de postgres

Coupure de liaison avec la base de données

La fermeture des connexions persistantes de postgresql via PHP peut être un problème lorsque la liaison avec la base de données est rompue.

On se retrouve alors avec une erreur de type :

Fatal error: Uncaught PDOException: SQLSTATE[57P01]: Admin shutdown: 7 FATAL: terminating connection due to administrator command server closed the connection unexpectedly This probably means the server terminated abnormally before or while processing the request.

Erreur de liaison avec la base de données

Installer un service sur le serveur applicatif pour supprimer les sockets en attente de fermeture

Une solution consiste à un installer un service sur le serveur applicatif pour supprimer les sockets en attente de fermeture.

Lorsque la liaison avec la base de données est rompue, PHP a toujours en cache le pool de connexion PDO vers des sockets en attente de fermeture. Ces dernières sont inutilisables, d'où l'erreur citée plus haut.

On peut consulter la liste des sockets en attente de fermeture à l'aide de la commande (il faut les droits root) :

netstat -anp | grep --regexp="5432" | grep CLOSE_WAIT

Le script PHP suivant permet de repérer ces sockets et de les fermer en tuant le process associé :

#créer le fichier /opt/maarch/killPgCloseWait.php
nano /opt/maarch/killPgCloseWait.php
<?php
$return = killCloseWait(['5432', 'CLOSE_WAIT']);

function killCloseWait ($match = []) {
    $matchString = '';
    foreach ($match as $aMatch) {
        $matchString .= ' grep ' . escapeshellarg($aMatch) . ' | ';
    }
    if (!empty($matchString)) {
        $cmd ='netstat -anp | ' . $matchString . " awk '{print $7}'";
        exec($cmd, $output, $return);
        if ($return) {
            //nothing
        } else {
            while (list(,$t) = each($output)) {
                if (preg_match('/^([0-9]+)/', $t, $r)) {
                    system('kill '. $r[1], $k);
                    if(!$k) $killed = 1;
                }
            }
        }
    }
}

Il nous reste plus qu'à créer un service exécutant ce code php pour se prémunir des ruptures de liaison avec la base de données lorsque l'on utilise les connexions persistantes de PDO.

nano /lib/systemd/system/killPgCloseWait.service
[Unit]
Description=kill close wait service
After=network.target
StartLimitIntervalSec=0

[Service]
Type=simple
Restart=always
RestartSec=1
User=root
ExecStart=/usr/bin/env php /opt/maarch/killPgCloseWait.php

[Install]
WantedBy=multi-user.target

Démarrer le service

systemctl start killPgCloseWait.service

Paramétrer le service pour qu'il se lance au boot de la machine

systemctl enable killPgCloseWait.service

Vérifier le statut du service

systemctl status killPgCloseWait.service

Vérifier que le service est efficace

  1. Lancer l'application MaarchCourrier depuis un navigateur web
  2. Redémarrer le serveur Postgres

    service postgresql restart

  3. Contrôler que toutes les sockets postgresql au statut CLOSE_WAIT sont bien fermées

    netstat -anp | grep --regexp="5432" | grep CLOSE_WAIT

results matching ""

    No results matching ""