Le lendemain matin, à mon retour, j'ai donc regardé à l'aide de la commande grep si des verrous étaient posés par les scripts PHP du site d'administration sur la base de données, aussi bien au niveau des tables qu'au niveau des lignes qu'elles contiennent, innodb permettant la pose de verrous à ce niveau notamment pour assurer l'intégrité de la base de données dans un contexte transactionnel.

Par acquis de conscience, j'ai également appliqué la même commande sur le journal de l'ensemble des requêtes SQL effectuées sur le serveur MySQL, activé temporairement pour l'occasion en environnement de pré-production. 

Ma recherche n'ayant rien donné et son résultat m'ayant été confirmés par les développeurs du site d'administration qui m'ont assuré que leur code ne posait aucun verrou à ce niveau, j'en ai déduit que ce dernier devait être posé sur un fichier soit par un script PHP, soit par Apache lui-même.

En effet, Apache est installé en mode prefork et il est de plus complété du module mod_itk qui permet d'attribuer un utilisateur et un groupe spécifique pour chaque processus apache correspondant à un site web précis.

Or, pour y parvenir, ce module provoque le fork du serveur apache dans son intégralité lorsqu'il reçoit une requête HTTP afin de pouvoir lui attribuer l'utilisateur et le groupe ad hoc.

Il est donc théoriquement possible que cette stratégie génère une situation de compétition vis à vis d'une ressource commune à l'ensemble des processus et qu'en conséquence, cela provoque le traitement séquentielle des requêtes et donc la baisse de performance constatée.

J'ai donc lancé la commande strace sur l'un des processus Apache du site d'administration afin de tenter de localiser la ressource concernée.

Cette commande est en effet un outil très puissant dans ce contexte, car elle permet de tracer l'ensemble des interactions entre un programme et le système de l'exploitation qui l'exécute.

Son utilisation m'a donc permis d'avoir la confirmation que nous étions sur la bonne piste, puisque j'ai alors été bombardé de message du type Resources unavailable, suivi d'un magnifique signal SIGCHLD indiquant la mort du processus concerné.

Je n'ai cependant pas eu d'indication quand à la nature de la ressource concernée, et j'ai donc alors décidé de demander conseil à des gens disposant de plus de compétences que moi en ce qui concerne l'administration et le fonctionnement d'un serveur Apache.

Un petit tour sur IRC et le canal adéquate (merci au passage aux plieurs de papier, ils se reconnaîtront) suivi d'une modification des règles de pare-feu du mod_status de Apache plus tard afin que mes contacts disposent des informations nécessaires, et j'avais la confirmation du fait que notre serveur HTTP forkait bien comme un malade et que cela pouvait tout à fait expliquer les mauvaises performances de notre solution.

En cadeau bonus, il m'a de plus été fourni deux solutions possibles, à savoir soit virer mod_itk pour revenir au fonctionnement classique de Apache en mode prefork, soit utiliser FastCGI pour gérer les requêtes PHP.

J'ai donc discuter des ces deux possibilités avec l'équipe, et après quelques explications sur leurs avantages et inconvénients respectifs, nous avons décidé de tester l'utilisation de FastCGI avec php-fpm, cette solution présentant en théorie de nombreux avantages, aussi bien en terme de performance que de configuration et de supervision.

En effet, php-fpm permet de définir des groupes de processus pour chacun des sites, groupes qu'il est possible de configurer finement et indépendamment en fonction des besoins, et de plus, son mode de fonctionnement reposant sur FastCGI permet de minimiser les opérations de fork nécessaires au traitement d'une requête HTTP et cette solution est donc plus efficace que le traditionnel couple Apache en prefork et mod_php.

J'avoue avoir pousser relativement fort dans cette direction au cours de la discussion, à la fois parce que je pensais que cela résoudrait notre problème et parce que je voulais depuis longtemps tester cette solution en production et que c'était la première fois que j'en avais l'occasion.

Pour nos tests, nous avons décidé d'utiliser un serveur jumeau de celui de notre client que nous utilisions pour nos besoins internes et que nous pouvions donc arrêter sans soucis le temps d'effectuer les installations et la configuration nécessaires.

Nous avons donc supprimé apache et mod_itk de notre serveur de test et nous avons installé et configuré en lieu et place la triplette Apache, mod_fastcgi et php-fpm et nous avons mis quelques heures à réaliser cela, car si la documentation pour installer tout cela est relativement abondante, elle n'est bien souvent plus à jour et de plus, elle se contente en général d'expliquer la configuration nécessaire pour gérer un seul site et non plusieurs sur un même serveur, d'autant que jusqu'à ce moment, je n'avais jamais mis en production php-fpm, tout comme mon administrateur système.

Cependant, après quelques prises de tête relativement intenses, nous sommes finalement parvenu à trouver une configuration suffisamment générique pour répondre à nos besoins à moindre frais.

Nous nous sommes alors empressé de répliquer les 10 Go de la base de données de production du client sur notre serveur de test, ainsi que les dernières versions du site de e-commerce et d'administration.

Et une fois cela fait, c'est avec jubilation que j'ai appuyer sur la touche F5 de mon clavier pour rafraîchir la page d'acceuil du site de e-commerce…

Et si vous voulez savoir ce qui s'est alors passé, il vous faudra patienter jusqu'au prochain épisode !