Rogers
| Membre
Inscrit le : 20/10/2010
|
# Le 11/01/2012 à 18:52
Bonjour,
Je gère la maintenance d'un site e-commerce depuis quelques mois, que j'ai commencé d'optimiser (cache, optimisation des requêtes sql...).
Toutefois, depuis aujourd'hui, début des soldes oblige, Apache fait monter la charge CPU à 100% et on obtient un load avg de plus de 50 (il est monté jusque 80).
Bref, j'ai repéré il y a quelques semaines une problématique sur une page qui comporte trop de produit. Avec les multiples images, le js on a trop de hits sur cette page. Pour soulager le serveur, j'ai pu installer une partie des fichiers images (tout l'habillage promotionnel en fait) sur mon propre dédié. Mais cette page reste encore trop gourmande. Enfin, c'est ce que je pensais, mais même en limitant la page à 70 produits (au lieu de 300 je crois), le load avg augmente toujours.
Du coup je me demande d'où peut venir ce problème. Il y a pas mal d'ajax sur le site et je ne vois pas comment identifier le problème. Je ne pense pas que ce soit un script PHP, je l'aurai déjà remarqué je pense. J'ai vraiment l'impression que c'est le nombre de hits demandés par chaque client qui engorge Apache.
Voici la configuration du serveur :
Type : Intel(R) Core(TM)2 Quad CPU ...
Vitesse : 2400.063 MHz
Cache : 4096 KB
Tourne sous Debian Etch
Concernant ma page problématique voici les infos avant mes modifs à 70 :
499 Requests 2.9 MB 24.17s (onload: 24.45s)
Voici ma commande top.
top - 18:45:02 up 167 days, 6:47, 1 user, load average: 38.34, 37.87, 31.28
Tasks: 152 total, 38 running, 114 sleeping, 0 stopped, 0 zombie
Cpu(s): 95.1%us, 4.3%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.2%hi, 0.4%si, 0.0%st
Mem: 4134168k total, 2248580k used, 1885588k free, 204808k buffers
Swap: 522104k total, 28k used, 522076k free, 1408184k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
27308 mysql 15 0 145m 54m 5456 S 29 1.3 62:25.93 mysqld
24420 www-data 16 0 28536 12m 5588 R 23 0.3 0:24.35 apache2
25071 www-data 15 0 25508 8328 4064 S 22 0.2 0:00.70 apache2
24237 www-data 16 0 28428 11m 4248 S 22 0.3 0:22.72 apache2
25073 www-data 16 0 28360 10m 4168 R 21 0.3 0:00.67 apache2
24509 www-data 15 0 28684 11m 4228 S 20 0.3 0:15.64 apache2
23517 www-data 16 0 29688 12m 4244 R 19 0.3 0:49.60 apache2
24529 www-data 16 0 28660 11m 4244 R 17 0.3 0:16.46 apache2
24220 www-data 16 0 28944 11m 4248 R 16 0.3 0:30.40 apache2
24231 www-data 15 0 25928 8980 4296 R 14 0.2 0:29.09 apache2
24236 www-data 15 0 26672 10m 5532 S 13 0.3 0:25.00 apache2
24472 www-data 16 0 28624 11m 4244 R 13 0.3 0:15.25 apache2
23133 www-data 15 0 31860 14m 4256 S 13 0.4 1:07.32 apache2
23790 www-data 16 0 28460 11m 4256 R 12 0.3 0:43.67 apache2
25072 www-data 16 0 29880 12m 4068 R 12 0.3 0:00.37 apache2
24773 www-data 16 0 29920 12m 4224 R 12 0.3 0:12.23 apache2
24230 www-data 16 0 28520 11m 4224 R 11 0.3 0:17.78 apache2
23527 www-data 15 0 26904 10m 4596 S 11 0.2 0:54.32 apache2
24221 www-data 15 0 28432 11m 4216 S 11 0.3 0:22.05 apache2
24486 www-data 16 0 28528 11m 4244 R 10 0.3 0:11.35 apache2
24119 www-data 16 0 28456 11m 4620 R 10 0.3 0:29.41 apache2
24052 www-data 16 0 29536 12m 4292 R 9 0.3 0:38.45 apache2
24683 www-data 16 0 29712 12m 4236 R 9 0.3 0:13.52 apache2
24239 www-data 16 0 28676 11m 4216 S 8 0.3 0:22.48 apache2
23505 www-data 15 0 28548 12m 5680 R 7 0.3 0:43.34 apache2
24637 www-data 16 0 28420 10m 4224 R 7 0.3 0:15.40 apache2
24155 www-data 16 0 29924 12m 4572 R 5 0.3 0:24.16 apache2
24224 www-data 15 0 26204 9176 4216 S 4 0.2 0:25.48 apache2
24156 www-data 15 0 26088 9128 4280 S 4 0.2 0:26.20 apache2
24419 www-data 15 0 26112 9156 4284 S 3 0.2 0:23.57 apache2
24133 www-data 16 0 29720 12m 4584 R 2 0.3 0:29.57 apache2
24238 www-data 15 0 29536 12m 4260 S 2 0.3 0:19.82 apache2
23092 www-data 16 0 29536 12m 4264 R 1 0.3 1:06.25 apache2
24118 www-data 16 0 29936 12m 4604 R 1 0.3 0:26.02 apache2
25070 www-data 16 0 26596 8840 3668 R 1 0.2 0:00.04 apache2
24227 www-data 16 0 29940 12m 4256 R 1 0.3 0:22.29 apache2
24206 www-data 16 0 29936 12m 4240 R 1 0.3 0:28.60 apache2
25063 www-data 18 0 28244 10m 3728 R 1 0.3 0:00.06 apache2
25068 www-data 15 0 28356 10m 3840 S 1 0.3 0:00.29 apache2
1469 root 15 0 2352 1264 852 R 0 0.0 0:10.59 top
5625 root 10 -5 0 0 0 S 0 0.0 55:23.79 kjournald
24682 www-data 15 0 31208 14m 4368 S 0 0.3 0:11.33 apache2
1 root 15 0 1940 636 544 S 0 0.0 0:02.66 init
J'ai aussi installé apachetop et j'ai pu voir que 2 fichiers php (avec du JS dedans), qui servent à afficher le zoom d'une image produit sont les plus demandés (après le fichier CSS) alors que ce zoom n'est dispo que sur les fiches produit. Un lien avec mon problème ?
Bref là j'ai limité la casse, j'ai pas mal joué avec le fichier conf, testé, retesté à tel point qu'il ne ressemble plus à rien mais me permet d'être entre 7 et 30 en load avg (le site est un peu lent mais est accessible) en heures de pointe.
Si l'un d'entre vous avait une idée pour débusquer le fautif, je lui en serait très reconnaissant. N'étant pas admin serveur même si j'administre le miens et la personne ayant installé le serveur n'étant plus disponible, j'avoue que ce soucis est en dehors de mes compétences
Cordialement,
Florent OPromos et codes remises - MaSolutionPaie - |
Bool
| Olivier Modérateur
Inscrit le : 09/05/2005
|
# Le 11/01/2012 à 20:17
Debian Etch daevel : infogérance et conseil || moi |
Bool
| Olivier Modérateur
Inscrit le : 09/05/2005
|
# Le 11/01/2012 à 23:06
Bon, on va essayer de t'aider un peu... je te mets ci dessous un bout de code que j'utilise chez mes clients afin de déterminer quels sont les scripts problématiques. Tu mets ça dans un fichier quelconque de ton système (/usr/local/share/foo.php par exemple), puis dans ton php.ini tu modifies la directive auto_prepend_file afin d'y mettre le chemin de ce fichier. Reste plus qu'à faire un reload d'Apache : /etc/init.d/apache2 reload
Le code en question :
<?php
define('__daevel_start', microtime());
ignore_user_abort(true);
$r = getrusage();
define('__daevel_rUser', bcadd(bcdiv($r['ru_utime.tv_usec'], 1000000, 3), $r['ru_utime.tv_sec'], 3));
define('__daevel_rSys', bcadd(bcdiv($r['ru_stime.tv_usec'], 1000000, 3), $r['ru_stime.tv_sec'], 3));
unset($r);
function __daevel_profiling()
{
$tmp = explode(' ', __daevel_start);
$start = $tmp[1] . substr($tmp[0], 1);
$tmp = explode(' ', microtime());
$end = $tmp[1] . substr($tmp[0], 1);
$elapsed = round(bcmul(bcsub($end, $start, 6), 1000, 3));
$memory = max(memory_get_peak_usage(), memory_get_peak_usage(true));
/**
* Si le script ne depasse pas le seuil, sort de suite.
*/
if( $elapsed < 300 and !connection_aborted() and $memory < 50*1024*1024 )
return;
$r = getrusage();
$rUser = ceil(bcmul(bcsub(bcadd(bcdiv($r['ru_utime.tv_usec'], 1000000, 3), $r['ru_utime.tv_sec'], 3),
__daevel_rUser, 3), 1000, 3));
$rSys = ceil(bcmul(bcsub(bcadd(bcdiv($r['ru_stime.tv_usec'], 1000000, 3), $r['ru_stime.tv_sec'], 3),
__daevel_rSys, 3), 1000, 3));
$aborted = connection_aborted();
$memory = str_pad(ceil($memory/(1024*1024)), 3, ' ', STR_PAD_LEFT) . 'MB';
$elapsed = str_pad($elapsed, 6, ' ', STR_PAD_LEFT) .'ms';
$rUser = str_pad($rUser, 6, ' ', STR_PAD_LEFT);
$rSys = str_pad($rSys, 4, ' ', STR_PAD_LEFT);
$serverName = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : '-';
$requestMethod = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'CLI';
$page = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : $_SERVER['argv'][0];
$addr = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '127.0.0.1';
$msg = "$memory $elapsed ($rUser+$rSys) ab:$aborted $serverName $requestMethod $page $addr";
/**
* Trace ces informations dans syslog.
*/
syslog(LOG_INFO, $msg);
}
register_shutdown_function('__daevel_profiling');
En l'état il va te tracer (dans /var/log/syslog) tous les scripts qui durent plus de 300ms, ou consomment plus de 50Mo de mémoire, ou bien ont été abandonnés par l'internaute avant que le script ne soit terminé.
La sortie va ressembler à ça ("tail -f /var/log/syslog" pour surveiller) :
Jan 11 22:48:16 front1 php5-cgi: 5MB 523ms ( 256+ 56) ab:0 www.domain.tld GET /forum/ 90.0.235.56
Jan 11 22:48:17 front1 php5-cgi: 1MB 408ms ( 0+ 4) ab:0 www.domain.tld GET /jolie/url-magique.htm 213.213.231.127
Jan 11 22:50:47 front1 php5-cgi: 1MB 3031ms ( 0+ 4) ab:0 www.domain.tld POST /write_user.php 204.19.10.193
/\ /\ /\ /\ /\
|| || || || ||
Col1 Col2 Col3 Col4 Col5
Et donc :
* Col1 = mémoire consommée
* Col2 = temps d'exécution total, en ms
* Col3 = temps d'utilisation CPU
* Col4 = temps d'utilisation système
* Col5 = l'utilisateur a-t-il abandonné ?
Ici la première ligne indique 523ms de traitement, dont 256ms d'utilisation CPU et 56ms système. 256ms de CPU c'est un code de goret, et 56ms de système indique probablement des accès disques.
La troisième ligne indique 3031ms de traitement, dont 0ms d'utilisation CPU et 4ms système : là le script a passé 3027ms à attendre la réponse d'un traitement externe (requête SQL, memcache, ou utilisation d'une API HTTP par exemple). Et vu l'URL, il y a fort à parier pour que le problème soit coté SQL.
Donc ça devrait te permettre d'identifier un peu plus en détail les scripts PHP fautifs... si toutefois c'est le cas. Dans ton cas tu utilises PHP en tant que module Apache, donc difficile de savoir si le problème se situe coté Apache ou PHP.
Mais c'est vrai que ta page de 24 secondes serait une bonne candidate, reste à voir si c'est la seule, s'il s'agit réellement d'utilisation CPU ou bien d'attente externe, puis restera à morceler le code pour trouver la zone qui fait tâche.
Bon courage en tous cas ! daevel : infogérance et conseil || moi |
Rogers
| Florent Membre
Inscrit le : 20/10/2010
|
# Le 12/01/2012 à 01:29
Ouah Bool avant toute chose merci d'avoir pris le temps de répondre et surtout d'avoir partagé ton script. Je ferais le test demain matin et te tiendrais au jus si j'ai pu y trouver quelque chose.
Concernant la Debian Etch, je sais, mais bon je ne peux pas tout révolutionner et ce n'est pas mon job l'administration serveur même si je fais quelques bricoles. L'autre jour, j'ai passé une journée pour pouvoir faire fonctionner un certificat SSL pour communiquer avec un service e-commerce sécurisé. La réponse du support de ce service a été simple : mettez à jour Open SSL (ce qui impliquait la Debian) ou passez en non sécurisé (la classe). J'ai pu feinter et signer le certificat par le serveur ce qui a résolu quasiment mon problème. Bref, la Debian Etch me pose soucis, mais je pense que mon client va peut être se décider avec tout ça à changer de serveur avec les derniers soucis rencontrés.
Mais avant de faire le changement, j'aimerai quand même trouver le soucis de ce mange CPU car passer sur un nouveau serveur avec des scripts incontrolables, très peu pour moi.
Encore une fois merci OPromos et codes remises - MaSolutionPaie - |
allogarage
| Nicolas Modérateur
Inscrit le : 14/10/2008
|
# Le 12/01/2012 à 10:12
Merci Bool pour avoir partagé ce script ! Guide comparatif des garages automobiles | Guide comparatif des garages moto | Annuaire auto moto |
krucial
| Jean Christophe Administrateur
Inscrit le : 09/03/2005
|
# Le 12/01/2012 à 10:42
Bool, balance une facture, je te fais un cheque JC - Mes sites | Affiliation devis travaux | Cotes voitures anciennes |
Rogers
| Florent Membre
Inscrit le : 20/10/2010
|
# Le 12/01/2012 à 11:19
Finalement ça a intéressé du monde :p.
Bool, encore une fois merci pour ce super script que j'ai installé et qui fonctionne à merveille. J'ai juste une petite question concernant l'interprétation des résultats. Tu as tout très bien expliqué, mais comment dois-je interprété cela :
Jan 12 11:12:09 xxxxxxx apache2: 7MB 337ms ( 320+ 8) ab:0 www.xxxxxxx.com GET /stylesheet1.css
Jan 12 11:12:09 xxxxxxx apache2: 7MB 636ms ( 356+ 8) ab:0 www.xxxxxxx.com GET /images/panier.png
Jan 12 11:12:09 xxxxxxx apache2: 7MB 633ms ( 340+ 12) ab:0 www.xxxxxxx.com GET /images/img_h.gif
Jan 12 11:12:09 xxxxxxx apache2: 7MB 412ms ( 328+ 20) ab:0 www.xxxxxxx.com GET /images/img_111111111111111.jpg
Il s'agit de fichiers statiques. Est-ce que je peux naturellement en conclure que les scripts php qui se trouvent avant (et que j'avais repéré avec apachetop) sont la cause et du coup on a un mauvais temps pour les fichiers statiques ?
Merci encore pour ton aide précieuse. OPromos et codes remises - MaSolutionPaie - |
Bool
| Olivier Modérateur
Inscrit le : 09/05/2005
|
# Le 12/01/2012 à 11:54
Gaffe kru, je vais te prendre au mot !
Rogers : "337ms ( 320+ 8)", ça veut dire que tu as 320ms de consommation CPU et 8ms de consommation système, pour un total de 337ms. Bref, ce "script" est super gourmand en CPU... s'il s'agit d'un script
Il s'agit de fichiers statiques.
Béh non justement. Là PHP se retrouve à interpréter tous tes fichiers "statiques", faut revoir ta configuration Apache. daevel : infogérance et conseil || moi |
Rogers
| Florent Membre
Inscrit le : 20/10/2010
|
# Le 12/01/2012 à 12:20
Ok, les scripts (il y en a 2) sont des checkers de stock. Cela vérifie à l'aide d'ajax que le produit avec les options désirées n'est ni en rupture, ni en train d'être commandé par un client. J'ai déjà corrigé de grosses erreurs dans la structure des tables MySQL. Mais bon le code est tellement mal conçu, sans commentaires et avec des variables qui n'indiquent pas ce qu'elles sont, que je vais devoir y aller à taton. Toutefois, je vois des boucles imbriquées, je parie que c'est là dedans.
Concernant la partie : "337ms ( 320+ 8)".
Je ne comprend absolument pas. On a un fichier statique (disons en théorie parce que tu me dis que non après), donc il ne devrait pas avoir un tel temps de traitement et indépendamment du script qui l'appel (même si c'est lui le soucis), je devrais avoir une grosse conso CPU sur le script mais pas sur le fichier statique, c'est bien ça ?
Béh non justement. Là PHP se retrouve à interpréter tous tes fichiers "statiques", faut revoir ta configuration Apache.
Je ne suis pas expert, mais là ça me semble impossible, n'est-ce pas un non-sens ? Par défaut, Apache ne fonctionne pas comme ça non ? D'ailleurs on indique clairement quels sont les fichiers à interpréter par PHP dans cette partie il me semble :
<IfModule mod_php5.c>
AddType application/x-httpd-php .php .phtml .php3
AddType application/x-httpd-php-source .phps
</IfModule>
Bref, ce n'est pas clair.
OPromos et codes remises - MaSolutionPaie - |
Bool
| Olivier Modérateur
Inscrit le : 09/05/2005
|
# Le 12/01/2012 à 12:34
Rogers a dit :Concernant la partie : "337ms ( 320+ 8)".
Je ne comprend absolument pas. On a un fichier statique (disons en théorie parce que tu me dis que non après), donc il ne devrait pas avoir un tel temps de traitement et indépendamment du script qui l'appel (même si c'est lui le soucis), je devrais avoir une grosse conso CPU sur le script mais pas sur le fichier statique, c'est bien ça ?
Tu ne devrais même pas avoir de traitement, et mon bout de code PHP ne devrait pas être traité du tout. Là quelque chose dans ta conf Apache fait que PHP traite tous les fichiers qui passe, ça plombe fatalement les performances.
Je ne suis pas expert, mais là ça me semble impossible, n'est-ce pas un non-sens ? Par défaut, Apache ne fonctionne pas comme ça non ?
C'est tout le problème oui. T'aurais pas non plus un fichier .htaccess qui traine ?
daevel : infogérance et conseil || moi |
Rogers
| Florent Membre
Inscrit le : 20/10/2010
|
# Le 12/01/2012 à 14:25
Hmm, j'y vois déjà plus clair. Merci.
Pour le stylesheet, c'est un fichier PHP avec un rewriting pour lui donner une extension .css. Je trouve cela plus propre.
Pour le reste, fichier js et fichiers images, je ne vois pas. Il y a bien un .htaccess mais dedans uniquement des règles de rewrite et de l'optimisation cache et deflate.
Par contre tu m'as donné une idée, en regardant les logs de ton script, je remarque que les fichiers traités (images et JS) ne sont pas appelés par le bon chemin.
ex : /xxx/xxx/xxx/inc/js/jquery-1.4.2.min.js
Dans cet exemple, c'est le fichier js qui se trouve dans /inc/js/ qui est appelé. Je ne sais par quel miracle Apache comprend qu'il faut aller le chercher à la racine dans /inc/js/ et non dans les répertoires fictifs créés par le rewrite.
Enfin, c'est vraiment ridicule, le mec qui a fait ça, voyant que ça marchait ne s'est pas posé de question mais c'est logique qu'il fallait faire des appels sur les fichiers depuis la racine.
Bref, merci pour ton aide, je suis en train de corriger tous les chemins. Le log apprécie et le CPU aussi . OPromos et codes remises - MaSolutionPaie - |
Bool
| Olivier Modérateur
Inscrit le : 09/05/2005
|
# Le 12/01/2012 à 14:31
Ce serait pas plutôt que toutes tes 404 sont renvoyées vers un script PHP ? daevel : infogérance et conseil || moi |
allogarage
| Nicolas Modérateur
Inscrit le : 14/10/2008
|
# Le 12/01/2012 à 15:00
Bon courage car ça à l'air plutot...bancal! Guide comparatif des garages automobiles | Guide comparatif des garages moto | Annuaire auto moto |
MathieuC
| Mathieu Modérateur
Inscrit le : 15/07/2005
|
# Le 12/01/2012 à 15:09
Bancal je sais pas, je pense que c'est plutôt la conception du site qui est comme ça...
J'imagine que c'est un CMS eCommerce, et donc que toute l'arborescence du site n'est en fait que des répertoires virtuels.
Donc tous les appels passent par un fichier PHP qui fait office de "proxy", et donc si tu appelle tes fichiers statiques par leur URL dans les répertoires virtuels, tous les appels passent par ce fichier PHP qui te retourne le fichier statique, c'est clairement ultra lourd... mais organisé comme ça par le CMS...
Effectivement, si tu peux mettre les URL des fichiers statiques en direct et non a travers les répertoires virtuels, tu vas éviter toute une couche très lourde et inutile |
Rogers
| Florent Membre
Inscrit le : 20/10/2010
|
# Le 12/01/2012 à 17:45
Re
Bizarrement les Js, images et autres s'affichent correctement (je ne sais pourquoi) mais si je tape l'URL j'ai bien un 404. 404 qui redirige sur une page d'erreur avec le header, le footer et une image au centre.
Allogarage > Merci. Effectivement c'est plus que bancal et ça me gonfle.
Telaxo > Oui c'est un CMS, Oscommerce pour ne pas le citer. Le problème c'est que ça a été "customisé" par une agence web limite grand luxe qui sous-traitait en Pologne. Le développeur parlait Français apparemment mais ne connaissait pas Oscommerce. On a des rajouts de partout, création de nouvelles fonctions alors qu'il aurait été plus simple de se servir des fonctions OSC. Le code ne comporte aucun commentaire, les variables n'ont pas de noms permettant un debuggage rapide et d'identifier de suite ce que c'est. Bref un vrai casse noix.
Oui toutes les catégories sont des répertoires virtuels. Donc pas le choix de travailler avec les URLs (YOUPI !!!) comme le fait Wordpress par exemple.
Enfin, je ne comprends pas comment le mec a pu concevoir un tel rewriting sans se poser la question. Et puis tant qu'à l'écran ça s'affichait, pourquoi se compliquer la vie !
Merci à vous
OPromos et codes remises - MaSolutionPaie - |
Bool
| Olivier Modérateur
Inscrit le : 09/05/2005
|
# Le 12/01/2012 à 17:56
reste la solution de coller un NginX ou un Varnish en front pour qu'il traite les fichiers statiques à la place d'Apache, qui a été pourri par OsCommerce daevel : infogérance et conseil || moi |
JeromeF
| Jérôme Membre
Inscrit le : 10/05/2005
|
# Le 13/01/2012 à 16:54
Ce script fonctionne-t-il aussi sous Mac sur un env. de dév ?
(je pose la question car j'ai essayé mais cela ne produit rien) |
abravanel666
| Sylvain Modérateur
Inscrit le : 19/07/2009
|
# Le 14/01/2012 à 11:30
Merci bool
Ton script c'est du lourd de chez lourd !
Le truc que je revais depuis des années ...
Merci de partager ca avec nous http://www.magasins-usine.info http://www.shoppingactu.com |
Bool
| Olivier Modérateur
Inscrit le : 09/05/2005
|
# Le 14/01/2012 à 12:30
mais de rien ;) Et donc, vous prenez tous un contrat d'infogérance chez moi maintenant ?
JeromeF : s'il y a un syslog sous MacOS, alors oui ; mais sinon tu peux remplacer l'appel syslog() par un appel à error_log() daevel : infogérance et conseil || moi |
JeromeF
| Jérôme Membre
Inscrit le : 10/05/2005
|
# Le 14/01/2012 à 13:26
Merci Bool. Cela marche bien.
J'ai nommé mon fichier bool.php ;) |