Pourquoi mon serveur Web abandonne-t-il les connexions avec une réinitialisation TCP à charge élevée?

10

J'ai une petite configuration VPS avec nginx. Je veux en tirer le plus de performances possible, j'ai donc expérimenté l'optimisation et les tests de charge.

J'utilise Blitz.io pour effectuer des tests de charge en OBTENANT un petit fichier texte statique et en rencontrant un problème étrange où le serveur semble envoyer des réinitialisations TCP une fois que le nombre de connexions simultanées atteint environ 2000. Je sais que c'est un très grande quantité, mais en utilisant htop, le serveur a encore beaucoup à épargner en temps CPU et en mémoire, donc je voudrais trouver la source de ce problème pour voir si je peux le pousser encore plus loin.

J'utilise Ubuntu 14.04 LTS (64 bits) sur un VPS Linode 2 Go.

Je n'ai pas assez de réputation pour publier ce graphique directement, alors voici un lien vers le graphique Blitz.io:

entrez la description de l'image ici

Voici ce que j'ai fait pour essayer de déterminer la source du problème:

  • La valeur de configuration nginx worker_rlimit_nofileest définie sur 8192
  • ont nofiledéfini la valeur 64000 pour les limites matérielles et logicielles pour rootet l' www-datautilisateur (en tant que nginx s'exécute) dans/etc/security/limits.conf
  • il n'y a aucune indication que quelque chose se passe mal /var/log/nginx.d/error.log(généralement, si vous rencontrez des limites de descripteurs de fichiers, nginx affichera des messages d'erreur le disant)

  • J'ai une configuration ufw, mais pas de règles de limitation de débit. Le journal ufw indique que rien n'est bloqué et j'ai essayé de désactiver ufw avec le même résultat.

  • Il n'y a aucune erreur indicative dans /var/log/kern.log
  • Il n'y a aucune erreur indicative dans /var/log/syslog
  • J'ai ajouté les valeurs suivantes /etc/sysctl.confet les ai chargées sysctl -psans effet:

    net.ipv4.tcp_max_syn_backlog = 1024
    net.core.somaxconn = 1024
    net.core.netdev_max_backlog = 2000
    

Des idées?

EDIT: J'ai fait un nouveau test, en augmentant à 3000 connexions sur un très petit fichier (seulement 3 octets). Voici le graphique Blitz.io:

Graphique Blitz.io

Encore une fois, selon Blitz, toutes ces erreurs sont des erreurs de «réinitialisation de la connexion TCP».

Voici le graphique de la bande passante Linode. Gardez à l'esprit que c'est une moyenne de 5 minutes, donc c'est un filtre passe-bas un peu (la bande passante instantanée est probablement beaucoup plus élevée), mais quand même, ce n'est rien:

entrez la description de l'image ici

CPU:

entrez la description de l'image ici

E / S:

entrez la description de l'image ici

Voici htopvers la fin du test: htop

J'ai également capturé une partie du trafic à l'aide de tcpdump sur un test différent (mais d'aspect similaire), démarrant la capture lorsque les erreurs ont commencé à arriver: sudo tcpdump -nSi eth0 -w /tmp/loadtest.pcap -s0 port 80

Voici le fichier si quelqu'un veut y jeter un œil (~ 20 Mo): https://drive.google.com/file/d/0B1NXWZBKQN6ETmg2SEFOZUsxV28/view?usp=sharing

Voici un graphique de la bande passante de Wireshark:

entrez la description de l'image ici (La ligne correspond à tous les paquets, les barres bleues sont des erreurs TCP)

D'après mon interprétation de la capture (et je ne suis pas un expert), il semble que les drapeaux TCP RST proviennent de la source de test de charge, pas du serveur. Donc, en supposant que quelque chose ne va pas du côté du service de test de charge, est-il sûr de supposer que cela est le résultat d'une sorte de gestion de réseau ou d'atténuation DDOS entre le service de test de charge et mon serveur?

Merci!

Erik Swan
la source
Votre fournisseur fait-il une sorte d'atténuation des DDoS? Cela peut interférer avec votre test.
Michael Hampton
@MichaelHampton Je suis assez certain que Linode ne fait pas ça.
EEAA
Pouvez-vous publier le graphique du réseau à partir du panneau de configuration Linode? Quelle est la bande passante occupée par ce test?
EEAA
J'ai fait un peu plus d'enquête et mis à jour le message d'origine avec beaucoup plus d'informations. J'ai également confirmé auprès de Linode qu'ils ne font pas d'atténuation DDOS, bien que cela ne signifie pas nécessairement qu'un fournisseur de réseau entre le service de test de charge et Linode n'en fait pas. Merci!
Erik Swan
1
Y a-t-il une raison pour laquelle vous n'avez installé que net.core.netdev_max_backlog2000? Plusieurs exemples que j'ai vus ont un ordre de grandeur plus élevé pour les connexions gigabit (et 10Gig).
Moshe Katz

Réponses:

1

Il peut y avoir un certain nombre de sources de réinitialisation de connexion. Le testeur de charge peut être hors des ports éphémères disponibles à partir desquels établir une connexion, un périphérique en cours de route (comme un pare-feu faisant NAT) peut avoir son pool NAT épuisé et ne peut pas fournir un port source pour la connexion, est là un équilibreur de charge ou un pare-feu de votre côté qui aurait pu atteindre une limite de connexion? Et si vous faites du NAT source sur le trafic entrant, cela peut également entraîner l'épuisement du port.

On aurait vraiment besoin d'un fichier pcap des deux côtés. Ce que vous voulez rechercher, c'est si une tentative de connexion est envoyée mais n'atteint jamais le serveur mais apparaît toujours comme si elle avait été réinitialisée par le serveur. Si tel est le cas, quelque chose le long de la ligne a dû réinitialiser la connexion. L'épuisement des pools NAT est une source courante de ce type de problèmes.

En outre, netstat -st peut vous fournir des informations supplémentaires.

GeorgeB
la source
1

Quelques idées à essayer, basées sur mes propres expériences de réglage similaires récentes. Avec références:

Vous dites que c'est un fichier texte statique. Juste au cas où il y aurait un traitement en amont, les sockets de domaine améliorent apparemment le débit TCP sur une connexion basée sur le port TC:

https://rtcamp.com/tutorials/php/fpm-sysctl-tweaking/ https://engineering.gosquared.com/optimising-nginx-node-js-and-networking-for-heavy-workloads

Quelle que soit la terminaison en amont:

Activez multi_accept et tcp_nodelay: http://tweaked.io/guide/nginx/

Désactivez le démarrage lent TCP: /programming/17015611/disable-tcp-slow-start http://www.cdnplanet.com/blog/tune-tcp-initcwnd-for-optimum-performance/

Optimiser la fenêtre de congestion TCP (initcwnd): http://www.nateware.com/linux-network-tuning-for-2013.html

JayMcTee
la source
1

Pour définir le nombre maximum de fichiers ouverts (si cela est à l'origine de votre problème), vous devez ajouter "fs.file-max = 64000" à /etc/sysctl.conf

Sean1e
la source
0

Veuillez regarder combien de ports sont en TIME_WAITétat à l'aide de la commande netstat -patunl| grep TIME | wc -let passez net.ipv4.tcp_tw_reuseà 1.

fgbreel
la source
Comment pourrais-je voir le nombre de ports dans l' TIME_WAITÉtat?
Erik Swan
Utilisation de netstatou ss. J'ai mis à jour ma réponse avec la commande complète!
fgbreel du
J'ai relancé le test et watch -n 1 'sudo netstat -patunl | grep TIME | wc -l'renvoie 0 tout au long du test. Je suis certain que les réinitialisations sont le résultat d'une atténuation DDOS par quelqu'un entre le testeur de charge et mon serveur, sur la base de mon analyse du fichier PCAP que j'ai posté ci-dessus, mais si quelqu'un pouvait confirmer ce serait génial!
Erik Swan