Nginx et php-fpm: impossible de se débarrasser des erreurs 502 et 504

J’ai un serveur Ubuntu et un site Web très chargé. Le serveur est:

  • Dédié à nginx, utilise php-fpm (sans apache), mysql est situé sur une machine différente
  • A 8 Go de RAM
  • Obtient environ 2000 requêtes par seconde.

Chaque processus php-fpm consum environ 65 Mo de RAM, selon la commande top :

commande supérieure

Mémoire libre:

 admin@myserver:~$ free -m total used free shared buffers cached Mem: 7910 7156 753 0 284 2502 -/+ buffers/cache: 4369 3540 Swap: 8099 0 8099 

PROBLÈME

Dernièrement, je rencontre de gros problèmes de performance. Très gros temps de réponse, très nombreux délais d’ Gateway Timeouts et le soir, lorsque la charge est élevée, 90% des utilisateurs ne voient que “Server not found” au lieu du site Web (je n’arrive pas à le reproduire)


LOGS

Mon journal des erreurs Nginx est plein des messages suivants:

 2012/07/18 20:36:48 [error] 3451#0: *241904 upstream prematurely closed connection while reading response header from upstream, client: 178.49.30.245, server: example.net, request: request: "GET /readarticle/121430 HTTP/1.1", upstream: "fastcgi://127.0.0.1:9001", host: "example.net", referrer: "http://example.net/articles" 

J’ai essayé de basculer vers un socket unix, mais toujours obtenir ces erreurs:

 2012/07/18 19:27:30 [crit] 2275#0: *12334 connect() to unix:/tmp/fastcgi.sock failed (2: No such file or directory) while connecting to upstream, client: 84. 237.189.45, server: example.net, request: "GET /readarticle/121430 HTTP/1.1", upstream: "fastcgi://unix:/tmp/fastcgi.sock:", host: "example.net", referrer: "http ://example.net/articles" 

Et php-fpm log en est rempli:

 [18-Jul-2012 19:23:34] WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 32 children, there are 0 idle, and 75 total children 

J’ai essayé d’augmenter les parameters jusqu’à 100 , mais cela ne semble toujours pas suffisant.


CONFIG

Voici ma configuration actuelle

php-fpm

 listen = 127.0.0.1:9001 listen.backlog = 4096 pm = dynamic pm.max_children = 130 pm.start_servers = 40 pm.min_spare_servers = 10 pm.max_spare_servers = 40 pm.max_requests = 100 

nginx

 worker_processes 4; worker_rlimit_nofile 8192; worker_priority 0; worker_cpu_affinity 0001 0010 0100 1000; error_log /var/log/nginx_errors.log; events { multi_accept off; worker_connections 4096; } http { include mime.types; default_type application/octet-stream; access_log off; sendfile on; keepalive_timeout 65; gzip on; # fastcgi parameters fastcgi_connect_timeout 120; fastcgi_send_timeout 180; fastcgi_read_timeout 1000; fastcgi_buffer_size 128k; fastcgi_buffers 4 256k; fastcgi_busy_buffers_size 256k; fastcgi_temp_file_write_size 256k; fastcgi_intercept_errors on; client_max_body_size 128M; server { server_name example.net; root /var/www/example/httpdocs; index index.php; charset utf-8; error_log /var/www/example/nginx_error.log; error_page 502 504 = /gateway_timeout.html; # rewrite rule location / { if (!-e $request_filename) { rewrite ^(.*)$ /index.php?path=$1 last; } } location ~* \.php { fastcgi_pass 127.0.0.1:9001; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_script_name; include fastcgi_params; } } } 

Je serais très reconnaissant pour tout conseil sur la façon d’identifier le problème et quels parameters je peux ajuster pour résoudre ce problème. Ou peut-être 8 Go de RAM ne suffit pas pour ce type de charge?

Un certain nombre de problèmes. Cela vaut encore la peine de les réparer avec un site aussi occupé. MySQL peut être la cause principale pour le moment. Mais à plus long terme, vous devez faire plus de travail.

Mise en cache

Je vois l’un de vos messages d’erreur montrant une demande d’access au php en amont. Cela ne semble pas bon avec un site aussi fréquenté (2000 r / s que vous avez mentionné). Cette page (/ readarticle / 121430) semble être une page parfaitement cachable. D’une part, vous pouvez utiliser nginx pour mettre en cache ces pages. Découvrez le cache fastcgi

 GET /readarticle/121430 

php-fpm

 pm.max_requests = 100 

La valeur signifie qu’un processus sera tué par php-fpm master après avoir traité 100 requêtes. php-fpm utilise cette valeur pour lutter contre les memory leaks de tiers. Votre site est très occupé, avec 2000r / s. Votre nombre maximum de processus enfants est de 130, chacun ne pouvant traiter que 100 demandes au maximum. Cela signifie qu’après 13000/2000 = 6,5 secondes, tous seront recyclés. C’est beaucoup trop (20 processus tués chaque seconde). Vous devriez au moins commencer avec une valeur de 1000 et augmenter ce nombre tant que vous ne voyez pas de fuite de mémoire. Quelqu’un utilise 10 000 en production.

nginx.conf

  • Question 1:

      if (!-e $request_filename) { rewrite ^(.*)$ /index.php?path=$1 last; } 

    devrait être remplacé par try_files plus efficace:

      try_files $uri /index.php?path=$uri; 

Vous enregistrez un supplément si le bloc d’emplacement et une règle de réécriture de regex correspondent.

  • Problème 2: l’utilisation de socket unix vous permettra d’économiser plus de temps que d’utiliser ip (environ 10 à 20% de mon expérience). C’est pourquoi php-fpm l’utilise par défaut.

  • Problème 3: Vous pouvez être intéressé par la configuration de connexions keepalive entre nginx et php-fpm. Un exemple est donné ici sur le site officiel de nginx.

J’ai besoin de voir vos parameters php.ini et je ne pense pas que cela soit lié à MySQL car vous obtenez des erreurs de socket à quoi il ressemble. Est-ce également quelque chose qui commence à se produire après un certain temps ou est-ce que cela se produit immédiatement au redémarrage du serveur?

Essayez de redémarrer le démon php5-fpm et de voir ce qui se passe tout en modifiant votre journal des erreurs.

Vérifiez votre fichier php.ini et tous vos fastcgi_params généralement situés dans / etc / nginx / fastcgi_params. Il y a une tonne d’exemples pour ce que vous essayez de faire.

De plus, avez-vous l’extension apc php cache activée?

Cela ressemblera à ceci dans votre fichier php.ini si vous êtes sur une stack de stacks:

extension = apc.so
….
apc.enabled = 0

Probablement ne serait pas mal de faire des tests de chargement de connexion mysql à partir de la ligne de commande ainsi que de voir quels sont les résultats.

La mise en place de nginx microcache serait également utile. Ce qui servira la même réponse pendant quelques secondes.

http://seravo.fi/2013/optimizing-web-server-performance-with-nginx-and-php a de bonnes informations sur les performances de nginx. Personnellement suivi et je suis très heureux.

pour avoir une réponse à cette question:

You should check your MySQL server. Probably it's overloaded or it limits count of parallel MySQL connections. You should find the bottleneck. And according to your top screenshot it doesn't look like either RAM or CPU, then it's most likely I/O. – @VBrat

Choses que vous pourriez vouloir faire à l’avenir:

1- Augmentez votre taille de RAM.

2- utiliser le cache. voir cet article sur la façon dont le cache peut accélérer votre site

3- réduire le nombre de requêtes exécutées.

  • Configurer l’extension APC pour PHP (vérifier / configurer)
  • MySQL – Vérifier la configuration, les index, les requêtes lentes
  • Installez et configurez Varnish. Cela peut mettre en cache les requêtes de page et être très utile pour réduire le nombre de requêtes php et de requêtes mysql à effectuer. Cela peut être difficile avec les cookies / ssl mais sinon pas trop difficile et très utile