8795 sujets

Développement web côté serveur, CMS

Bonjour,

Je tente d'exploiter un serveur Web Apache pour des besoins de fort traffic.
Mon but est d'uploader une image via un client pour qu'elle se retrouve rangée dans un répertoire sur un serveur.

J'utilise pour cela une page php côté serveur qui récupère l'image sous forme de données PUT pour ne pas créer un fichier temporaire.

La difficulté est de pouvoir uploader 10 images par seconde (donc faire 10 requêtes à la seconde) et que le temps d’exécution du PHP soit à peu
près stable.

Ce que je ne comprends pas, c'est que parfois, le temps d'execution du PHP part à près de 800 millisecondes quand les autres requêtes se font en moins de 10 millisecondes.

Les images uploadées font toutes 100ko.

Voici les conditions/informations de mon environnement côté client et côté serveur.

Côté client :

La machine a un processeur BiPro, 12Go de RAM avec Linux Debian.

- Pour envoyer une requête au serveur, j'utilise curl avec l'options "-X PUT nom_du_fichier".
- J'ai mis la commande curl dans un shell pour cadencer le nombre de requête à 10 requêtes par secondes (en faisant un sleep entre chaque requête). Les requêtes sont donc éxecutées en série.
- L'image uploadée a été copiée 1000 fois pour que chaque paquet de 1000 requêtes n'utilise pas la même ressource.
- J'ai mis l'option net.ipv4.tcp_tw_reuse = 0.
- La requête curl va pointer sur un fichier PHP sur mon serveur qui va stocker le fichier envoyé par PUT et retourner le temps d'execution de PHP ainsi que l'heure d'appel de la page sous forme HH:MM:SS.mmm. La sortie est redirigée vers un fichier en utilisant " >> fichier_sortie.json"

Entre le client et le serveur :

- C'est un réseau Gigabit

Côté client :

- La machine a aussi un processeur BiPro, 12Go de RAM avec Linux Debian.
- J'ai installé un serveur Apache 2.2.22, avec le mod_fastcgi pour utiliser PHP-FPM.
- Je fais travailler le serveur Apache avec des workers définis dans le apache2.conf.

Voici quelques informations dans ce fichier qui me paraissent importantes :

Fichier /etc/apache2/apache2.conf :

Timeout 300

KeepAlive On

MaxKeepAliveRequests 100

KeepAliveTimeout 2

<IfModule mpm_worker_module>
 StartServers        8
 MaxClients          256
 MinSpareThreads     96
 MaxSpareThreads     96
 ThreadsPerChild     32
 MaxRequestsPerChild  4000
</IfModule>

Et les informations pour PHP-FPM

Fichier /etc/php5/fpm/php-fpm.conf :

events.mechanism = epoll


Fichier /etc/php5/fpm/pool.d/www.conf :


pm = static
pm.max_children = 96
pm.min_spare_servers = 32
pm.max_spare_servers = 32

J'ai retiré le maximum d'écriture de log et sinon j'ai mis le niveau de log à "crit"

Informations supplémentaires :
J'utilise un rewrite pour accéder à ma page PHP.

J'ai réalisé un test sur 12h et voici le genre de fichier que j'obtiens (c'est un petit morceau)

{Time:19:34:45.012,Date:0.005},
{Time:19:34:45.134,Date:0.004},
{Time:19:34:45.257,Date:0.005},
{Time:19:34:45.381,Date:0.005},
{Time:19:34:45.504,Date:0.004},
{Time:19:34:45.627,Date:0.005},
{Time:19:34:45.749,Date:0.005},
{Time:19:34:46.670,Date:0.802},
{Time:19:34:46.797,Date:0.006},
{Time:19:34:46.920,Date:0.005},
{Time:19:34:47.044,Date:0.005},
{Time:19:34:47.168,Date:0.005},
{Time:19:34:47.293,Date:0.005},
{Time:19:34:47.417,Date:0.005},


En ratio, j'ai une image "qui dévie" sur 200.

J'ai essayé sur un test de 2000 images, le ratio est le même bien que le temps maximal d’exécution soit d'environ 400 ms.
Mes différentes hypothèses sont :

- Les workers de mon Apache sont mal dimensionnés.
- La configuration de mon PHP-FPM est inadaptée.
- L'écriture du fichier de sortie plombe le mécanisme (ouverture et fermeture de la même ressource en permanence)
- L'écriture des fichiers côté serveur n'arrive pas à suivre (saturation sur le réseau Gigabit ou dans le Linux serveur)

Est-ce que quelqu'un a déjà été confronté à cette situation?
Merci d'avance de m'avoir lu et pour l'aide que vous pourrez me fournir.

Cordialement
Je serais très loin de pouvoir prétendre à une solution, mais voici quelques réflexions

L'écriture du fichier de sortie plombe le mécanisme (ouverture et fermeture de la même ressource en permanence)

Si par fichier de sortie tu entends par là ton fichier de statistiques JSON côté client, je dirais non. Si le problème était là, tu observerais certainement que le temps d'exécution du script php serait normal, et que c'est le temps entre deux envois successifs qui serait anormalement long. Or, là, si on regarde bien, les temps totaux d'exécution des requêtes en comprenant envoi/réception mais en faisant abstraction du temps d'exécution du script php est toujours aux alentours de 10-30ms.


Avec le même argument, j'excluerais aussi un problème de transmission sur le réseau, car ces 10-30ms plutôt stables comprennent le temps de transfert. Quoi qu'il pourrait être instructif de lancer ton test en local (comprendre envoie et réception sur la même machine) pour voir si ça change quelque chose.

Tu confirmes que rien d'autre de significatif ne tourne sur le serveur au moment où tu fais les tests, et que personne d'autre ne fait des requêtes ? Parce qu'évidemment, n'importe quel évènement extérieur est suceptible de fausser tes résultats ou bloquer les process apache/php. Je pense à deux choses: un garbage collector (je ne sais pas comment fonctionne ton module apache ni si tu as des extensions php spéciales qui le font donc difficile de savoir si c'est plausible ou non), ou alors peut-être un cache disque ou un autre truc du genre qui prendrait temporairement tout le CPU (si tu as du RAID soft je pense que c'est plausible).
Bonjour et merci pour ta réponse.

Je viens de lancer le même test en local et je constate le même résultat.
J'ai trouvé une commande qui permet de vider le cache sur ma machine serveur.

Cette commande est
echo 3 > /proc/sys/vm/drop_caches


J'ai fait un bash pour l'executer toutes les 3 secondes pendant que j'envoie les images.

Je ne constate que peu d'effets, le cache augmente quand même, même si il a l'air de se stabiliser après avoir atteint une valeur de 55Mo.

Je n'ai pas installé d'extensions supplémentaires côté apache, à part fast_cgi.
En voici d'ailleurs la liste :


actions.load
alias.load
auth_basic.load
authn_file.load
authz_default.load
authz_groupfile.load
authz_host.load
authz_user.load
autoindex.load
cache.load
cgid.load
cgi.load
deflate.load
dir.load
env.load
fastcgi.load
mime.load
negotiation.load
reqtimeout.load
rewrite.load
setenvif.load
status.load
userdir.load
vhost_alias.load
setenvif.load
status.load
userdir.load
vhost_alias.load


Sais-tu si j'ai un moyen d'agir sur le garbage collector?