Je travaille pour un site Internet plutôt occupé qui reçoit souvent de très fortes pointes de trafic. Pendant ces pics, des centaines de pages par seconde sont demandées, ce qui génère 502 erreurs de passerelle aléatoires.
Nous exécutons maintenant Nginx (1.0.10) et PHP-FPM sur une machine équipée de 4x SAS lecteurs 15k (raid10) avec un processeur à 16 cœurs et 24 Go de RAM DDR3. Nous utilisons également la dernière version de Xcache. La base de données est située sur une autre machine, mais la charge de cette machine est très faible et ne présente aucun problème.
Sous charge normale, tout fonctionne parfaitement, la charge du système est inférieure à 1, et le rapport sur l'état de PHP-FPM ne montre jamais plus de 10 processus actifs à la fois. Il reste toujours environ 10 Go de RAM. En charge normale, la machine gère environ 100 pages vues par seconde.
Le problème se pose lorsque d’importants pics de trafic arrivent et que centaines de pages vues par seconde sont demandées à la machine. Je remarque que le rapport d’état de FPM indique alors jusqu’à 50 processus actifs, mais c’est encore bien en dessous des 300 connexions maximum configurées. Au cours de ces pics, l’état Nginx rapporte jusqu’à 5 000 connexions actives au lieu de la moyenne normale de 1 000.
Informations sur le système d'exploitation: CentOS version 5.7 (finale)
CPU: processeur E5620 @ 2.40GH d'Intel (R) Xeon (R) (16 cœurs)
php-fpm.conf
daemonize = yes
listen = /tmp/fpm.sock
pm = static
pm.max_children = 300
pm.max_requests = 1000
Je n'ai pas configuré rlimit_files, car, autant que je sache, il devrait utiliser la valeur par défaut du système si vous ne le faites pas.
fastcgi_params (uniquement des valeurs ajoutées au fichier standard)
fastcgi_connect_timeout 60;
fastcgi_send_timeout 180;
fastcgi_read_timeout 180;
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
fastcgi_intercept_errors on;
fastcgi_pass unix:/tmp/fpm.sock;
nginx.conf
worker_processes 8;
worker_connections 16384;
sendfile on;
tcp_nopush on;
keepalive_timeout 4;
Nginx se connecte à FPM via Unix Socket.
sysctl.conf
net.ipv4.ip_forward = 0
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.accept_source_route = 0
kernel.sysrq = 1
kernel.core_uses_pid = 1
net.ipv4.tcp_syncookies = 1
kernel.msgmnb = 65536
kernel.msgmax = 65536
kernel.shmmax = 68719476736
kernel.shmall = 4294967296
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.tcp_timestamps = 0
net.ipv4.conf.all.rp_filter=1
net.ipv4.conf.default.rp_filter=1
net.ipv4.conf.eth0.rp_filter=1
net.ipv4.conf.lo.rp_filter=1
net.ipv4.ip_conntrack_max = 100000
limits.conf
* soft nofile 65536
* hard nofile 65536
Voici les résultats pour les commandes suivantes:
ulimit -n
65536
ulimit -Sn
65536
ulimit -Hn
65536
cat /proc/sys/fs/file-max
2390143
Question: Si PHP-FPM ne manque pas de connexions, que la charge est toujours basse et qu'il y a beaucoup de RAM disponibles, quel goulot d'étranglement pourrait être la cause de ces erreurs de passerelle 502 aléatoires lors de trafic intense?
Note: par défaut les ulimits de cette machine étaient 1024, puisque je l'ai changé en 65536, je n'ai pas complètement redémarré la machine, car c'est une machine de production et cela signifierait trop de temps d'arrêt.
Cela devrait résoudre le problème ...
Vous avez: fastcgi_buffers 4 256k;
Remplacez-le par: fastcgi_buffers 256 16k; // 4096k au total
Définissez également fastcgi_max_temp_file_size 0 , qui désactivera la mise en mémoire tampon sur le disque si les réponses commencent à dépasser les tampons fastcgi.
Le socket Unix accepte 128 connexions par défaut. Il est bon de mettre cette ligne dans /etc/sysctl.conf
net.core.somaxconn = 4096
Si cela ne vous aide pas dans certains cas, utilisez la liaison de port normale au lieu de socket, car socket sur 300+ peut bloquer les nouvelles demandes forçant nginx à afficher 502.
@M. Aubaine
J'ai 8 RAM de base de 14 Go. Mais le système donne très souvent le délai d'attente de la passerelle.
La mise en œuvre du correctif ci-dessous n'a pas non plus résolu le problème. Toujours à la recherche de meilleures solutions.
Vous avez: fastcgi_buffers 4 256k;
Changez le en:
fastcgi_buffers 256 16k; // 4096k au total
Définissez également fastcgi_max_temp_file_size 0, qui désactivera la mise en mémoire tampon sur le disque si les réponses commencent à dépasser vos tampons fastcgi
.
Merci.