Je cherche à comprendre certains problèmes de performances du serveur que je vois avec un serveur Web (pour nous) lourdement chargé. L'environnement est le suivant:
- Debian Lenny (tous les packages stables + patché aux mises à jour de sécurité)
- Apache 2.2.9
- PHP 5.2.6
- Grande instance Amazon EC2
Le comportement que nous constatons est que le Web se sent généralement réactif, mais avec un léger retard pour commencer à traiter une demande - parfois une fraction de seconde, parfois 2 à 3 secondes dans nos heures d'utilisation maximales. La charge réelle sur le serveur est signalée comme très élevée - souvent 10.xx ou 20.xx comme indiqué par top
. De plus, l'exécution d'autres choses sur le serveur pendant ces périodes (même vi
) est très lente, donc la charge est définitivement là-haut. Curieusement, Apache reste très réactif, à part ce délai initial.
Nous avons configuré Apache comme suit, en utilisant prefork:
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxClients 150
MaxRequestsPerChild 0
Et KeepAlive en tant que:
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5
En regardant la page d'état du serveur, même en ces temps de forte charge, nous atteignons rarement le plafond du client, servant généralement entre 80 et 100 demandes et bon nombre de celles en état de conservation. Cela me dit d'exclure la lenteur de la demande initiale comme "en attente d'un gestionnaire" mais je peux me tromper.
La surveillance CloudWatch d'Amazon me dit que même lorsque notre système d'exploitation signale une charge> 15, l'utilisation de l'UC de notre instance se situe entre 75 et 80%.
Exemple de sortie de top
:
top - 15:47:06 up 31 days, 1:38, 8 users, load average: 11.46, 7.10, 6.56
Tasks: 221 total, 28 running, 193 sleeping, 0 stopped, 0 zombie
Cpu(s): 66.9%us, 22.1%sy, 0.0%ni, 2.6%id, 3.1%wa, 0.0%hi, 0.7%si, 4.5%st
Mem: 7871900k total, 7850624k used, 21276k free, 68728k buffers
Swap: 0k total, 0k used, 0k free, 3750664k cached
La majorité des processus ressemblent à:
24720 www-data 15 0 202m 26m 4412 S 9 0.3 0:02.97 apache2
24530 www-data 15 0 212m 35m 4544 S 7 0.5 0:03.05 apache2
24846 www-data 15 0 209m 33m 4420 S 7 0.4 0:01.03 apache2
24083 www-data 15 0 211m 35m 4484 S 7 0.5 0:07.14 apache2
24615 www-data 15 0 212m 35m 4404 S 7 0.5 0:02.89 apache2
Exemple de sortie vmstat
en même temps que ci-dessus:
procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
8 0 0 215084 68908 3774864 0 0 154 228 5 7 32 12 42 9
6 21 0 198948 68936 3775740 0 0 676 2363 4022 1047 56 16 9 15
23 0 0 169460 68936 3776356 0 0 432 1372 3762 835 76 21 0 0
23 1 0 140412 68936 3776648 0 0 280 0 3157 827 70 25 0 0
20 1 0 115892 68936 3776792 0 0 188 8 2802 532 68 24 0 0
6 1 0 133368 68936 3777780 0 0 752 71 3501 878 67 29 0 1
0 1 0 146656 68944 3778064 0 0 308 2052 3312 850 38 17 19 24
2 0 0 202104 68952 3778140 0 0 28 90 2617 700 44 13 33 5
9 0 0 188960 68956 3778200 0 0 8 0 2226 475 59 17 6 2
3 0 0 166364 68956 3778252 0 0 0 21 2288 386 65 19 1 0
Et enfin, sortie d'Apache server-status
:
Server uptime: 31 days 2 hours 18 minutes 31 seconds
Total accesses: 60102946 - Total Traffic: 974.5 GB
CPU Usage: u209.62 s75.19 cu0 cs0 - .0106% CPU load
22.4 requests/sec - 380.3 kB/second - 17.0 kB/request
107 requests currently being processed, 6 idle workers
C.KKKW..KWWKKWKW.KKKCKK..KKK.KKKK.KK._WK.K.K.KKKKK.K.R.KK..C.C.K
K.C.K..WK_K..KKW_CK.WK..W.KKKWKCKCKW.W_KKKKK.KKWKKKW._KKK.CKK...
KK_KWKKKWKCKCWKK.KKKCK..........................................
................................................................
De mon expérience limitée, je tire les conclusions / questions suivantes:
Nous pouvons accepter beaucoup trop de
KeepAlive
demandesJe vois un peu de temps passé à attendre les E / S dans le vmstat, mais pas régulièrement et pas beaucoup (je pense?), Donc je ne suis pas sûr que ce soit une grande préoccupation ou non, je suis moins expérimenté avec vmstat
Toujours dans vmstat, je vois dans certaines itérations un certain nombre de processus en attente d'être servis, ce à quoi j'attribue le délai de chargement de page initial sur notre serveur Web, peut-être à tort
Nous servons un mélange de contenu statique (75% ou plus) et de contenu de script, et le contenu du script est souvent assez gourmand en processeur, il est donc important de trouver le bon équilibre entre les deux; à long terme, nous voulons déplacer la statique ailleurs pour optimiser les deux serveurs, mais notre logiciel n'est pas prêt pour cela aujourd'hui
Je suis heureux de fournir des informations supplémentaires si quelqu'un a des idées, l'autre note est qu'il s'agit d'une installation de production à haute disponibilité, donc je me méfie de faire des ajustements après ajustements, et c'est pourquoi je n'ai pas joué avec des choses comme la KeepAlive
valeur moi-même encore.
Réponses:
Je commencerai par admettre que je n'ai pas grand-chose à faire avec des choses dans les nuages - mais d'après mon expérience ailleurs, je dirais que cette configuration de serveur Web reflète un volume de trafic assez faible. Le fait que la file d'attente soit si grande suggère qu'il n'y a tout simplement pas assez de CPU disponible pour y faire face. Qu'y a-t-il d'autre dans la file d'attente?
Non - keeplive améliore toujours les performances, les navigateurs modernes sont très intelligents pour savoir quand canaliser et quand exécuter des requêtes en parallèle, bien qu'un délai de 5 secondes soit encore assez élevé, et vous avez BEAUCOUP de serveurs en attente - sauf si vous '' J'ai des problèmes de latence ÉNORMES, je recommanderais de le réduire à 2-3. Cela devrait raccourcir un peu la file d'attente.
Si vous n'avez pas déjà installé mod_deflate sur le serveur Web - alors je vous recommande de le faire - et ajoutez l'ob_gzhandler () à vos scripts PHP. Vous pouvez le faire en tant que pré-ajout automatique:
(Oui, la compression utilise plus de CPU - mais vous devriez économiser le CPU dans l'ensemble en retirant les serveurs de la file d'attente plus rapidement / en gérant moins de paquets TCP - et en bonus, votre site est également plus rapide).
Je recommanderais de fixer une limite supérieure à MaxRequestsPerChild - dites quelque chose comme 500. Cela permet simplement un certain roulement des processus au cas où vous auriez une fuite de mémoire quelque part. Vos processus httpd semblent ÉNORMES - assurez-vous d'avoir supprimé tous les modules apache dont vous n'avez pas besoin et assurez-vous de fournir du contenu statique avec de bonnes informations de mise en cache.
Si vous rencontrez toujours des problèmes, le problème est probablement dans le code PHP (si vous passez à l'utilisation de fastCGI, cela devrait être évident sans pénalité de performance majeure).
mise à jour
Si le contenu statique ne varie pas beaucoup d'une page à l'autre, il peut également être utile d'expérimenter avec:
sur les scripts PHP aussi.
la source
Vous devriez envisager d'installer un proxy inverse asynchrone, car un certain nombre de processus à l'état W sont également assez élevés. Vos processus Apache semblent passer beaucoup de temps à envoyer du contenu à des clients lents sur le réseau bloqués. Nginx ou lighttpd en tant que frontend pour votre serveur Apache peut réduire considérablement un certain nombre de processus dans l'état W. Et oui, vous devez limiter un certain nombre de requêtes Keepalive. Il vaut probablement la peine d'essayer de désactiver Keepalive.
BTW, 107 processus Apache sont trop élevés pour 22 rps, j'ai pu servir 100-120 rps en utilisant seulement 5 processus Apache. Probablement, la prochaine étape consiste à profiler votre application.
la source
Vous avez deux lignes dans votre vmstat qui montrent que votre temps d'attente CPU est assez élevé, et autour de celles-ci, vous faites un bon nombre d'écritures (io-bo) et de changement de contexte. Je regarderais ce qui écrit des blocs et comment éliminer cette attente. Je pense que la plus grande amélioration pourrait être trouvée dans l'amélioration de votre E / S de disque. Vérifiez syslog - définissez-le pour écrire asynchrone. Assurez-vous que le cache d'écriture de votre contrôleur fonctionne (vérifiez-le - vous pourriez avoir une mauvaise batterie).
Keepalive ne cause pas votre problème de performance, il vous fait gagner du temps sur la configuration de la connexion si vous n'exécutez pas de cache en face. Vous pourriez bousculer un peu MaxSpareServers de sorte que dans un resserrement, vous n'attendez pas toutes les fourches.
la source
vous devriez envisager de désactiver keepalive comme un premier essai ...
avec 107 demandes traitées, je garderais MaxSpareServers plus haut que ce que vous avez défini ...
IMHO dans le nginx à long terme en tant que proxy inverse pour le contenu statique doit être pris en considération
la source
Première suggestion: désactiver les Keepalives. Je n'en ai jamais eu besoin que lorsque j'ai pu identifier une situation spécifique où les performances ont augmenté, mais en général, les requêtes / s ont diminué avec Keepalive activé.
Deuxième suggestion: définissez un MaxRequestsPerChild. Je fais écho à symcbean ici, cela aidera au basculement de processus en cas de fuite de mémoire. 500 est un bon point de départ.
Troisième suggestion: augmenter les MaxClients. Un calcul approximatif pour cela est (mémoire physique - mémoire utilisée par un processus non httpd) / taille de chaque processus httpd. Selon la façon dont httpd a été compilé, ce nombre est au maximum de 255. J'utilise 250 pour mes serveurs publics pour gérer Google / Yahoo / MS en explorant les systèmes.
Quatrième suggestion: augmenter les MaxSpareServers: quelque chose comme 4-5x MinSpareServers.
À moins que ces suggestions échouent, je regarderais l'équilibrage de charge avec reverse-proxy ou memcache pour DB.
la source