Einführung in die Fallstricke der hohen Parallelität und Leistungsoptimierung unter Linux

Einführung in die Fallstricke der hohen Parallelität und Leistungsoptimierung unter Linux

Vorwort

Das Linux-Betriebssystem ist heute das bevorzugte Betriebssystem für Server. Unter den Standardsystemparametern von Linux bietet Linux keine sehr gute Unterstützung für hohe Parallelität. Der Herausgeber beschäftigt sich seit vielen Jahren mit der Anwendungsentwicklung unter Linux. In Bezug auf hohe Parallelität unter Linux-Systemen ist der Herausgeber auf die Fallstricke gestoßen und weiß, wie man diese Fallstricke löst. Hier sind einige Hinweise, damit Sie nicht erneut in diese Fallstricke tappen.

Analyse und Lösung des Problems „Zu viele geöffnete Dateien“ während der Ausführung einer Linux-Anwendung

img

Der Grund für diese Eingabeaufforderung ist, dass die Anzahl der vom Programm geöffneten Datei-Socket-Verbindungen den Systemeinstellungswert überschreitet.

Überprüfen Sie die maximale Anzahl an Dateien, die jeder Benutzer öffnen darf

ulimit -a

Die Option „Dateien öffnen (-n) 1024“ gibt an, dass die maximale Anzahl an Dateien, die jeder Benutzer öffnen darf, 1024 beträgt.

Die maximale Anzahl von Dateihandles im aktuellen System. Dies wird nur zur Anzeige verwendet und kann nicht festgelegt oder geändert werden.

cat /proc/sys/fs/datei-max

Zeigen Sie das Limit für geöffnete Dateien für einen Prozess an

Katze /proc/10446(pid)/Grenzen

Festlegen der numerischen Methode für geöffnete Dateien

ulimit -n 65535

Diese Einstellungsmethode wird nach dem Neustart auf den Standardwert zurückgesetzt.

Dauerhafte Abbindemethode:

vim /etc/security/limits.conf

Am Ende hinzufügen

* Soft-Nofile 65535

* hartes Nofile 65535

Das System muss neu gestartet werden, damit die Änderungen wirksam werden

Nach dieser Änderung war das Problem wirksam gelöst.

Analyse und Lösung übermäßiger Wartezeiten bei hoher Parallelität in Linux

Das Phänomen besteht darin, dass der Server Anwendungen in Szenarien mit hoher Parallelität verzögert ausführt.

Methode zur Fehlerbehebung: Überprüfen Sie die Serverkonfiguration:

netstat -ant|awk '/^tcp/ {++S[$NF]} ENDE {für (a in S) drucken (a,S[a])}'

Es wurde festgestellt, dass zu viele Time_WAIT-Einträge vorhanden sind, Zehntausende, was einer großen Anzahl von Sockets im TIME_WAIT-Status entsprechen sollte. Wenn die gleichzeitige Nutzung der Clients weiterhin hoch ist, zeigen einige Clients an, dass sie keine Verbindung herstellen können.
Beschreibung des TCP-Verbindungsstatus:

CLOSED: Keine Verbindung aktiv oder im Aufbau LISTEN: Der Server wartet auf einen eingehenden Anruf SYN_RECV: Eine Verbindungsanforderung ist eingetroffen und wartet auf Bestätigung SYN_SENT: Die Anwendung wurde gestartet und öffnet eine Verbindung ESTABLISHED: Normaler Datenübertragungsstatus FIN_WAIT1: Die Anwendung meldet, dass sie fertig ist FIN_WAIT2: Die andere Seite hat der Freigabe zugestimmt ITMED_WAIT: Wartet, bis alle Pakete verfallen CLOSING: Beide Seiten versuchen gleichzeitig zu schließen TIME_WAIT: Die andere Seite hat eine Freigabe eingeleitet LAST_ACK: Wartet, bis alle Pakete verfallen

Die Gefahren von zu viel TIME_WAIT

Wenn die Netzwerkbedingungen nicht gut sind und die aktive Partei nicht auf TIME_WAIT wartet, stellen die aktive Partei und die passive Partei nach dem Schließen der vorherigen Verbindung eine neue TCP-Verbindung her. Zu diesem Zeitpunkt wirkt sich das von der passiven Partei erneut übertragene oder verzögerte FIN-Paket direkt auf die neue TCP-Verbindung aus.
Wenn die Netzwerkbedingungen nicht gut sind und keine TIME_WAIT-Wartezeit vorhanden ist, wird nach dem Schließen der Verbindung keine neue Verbindung hergestellt. Wenn ein erneut gesendetes oder verzögertes FIN-Paket von der passiven Partei empfangen wird, wird ein RST-Paket an die passive Partei zurückgegeben, was sich auf andere Dienstverbindungen der passiven Partei auswirken kann.

Die Antwort auf die Frage, wie sich das Problem zu vieler TIME_WAITs lösen lässt, lautet wie folgt:

Bearbeiten Sie die Kerneldatei /etc/sysctl.conf und fügen Sie den folgenden Inhalt hinzu:

net.ipv4.tcp_syncookies = 1 #Zeigt die Aktivierung von SYN-Cookies an. Wenn die SYN-Warteschlange überläuft, aktivieren Sie Cookies, um sie zu verarbeiten. Dadurch können einige SYN-Angriffe verhindert werden. Der Standardwert ist 0, was geschlossen bedeutet.
net.ipv4.tcp_tw_reuse = 1 #Zeigt an, dass die Wiederverwendung aktiviert ist. Erlaubt die Wiederverwendung von TIME-WAIT-Sockets für neue TCP-Verbindungen. Der Standardwert ist 0, was geschlossen bedeutet.
net.ipv4.tcp_tw_recycle = 1 #Zeigt an, dass die schnelle Wiederverwendung von TIME-WAIT-Sockets in TCP-Verbindungen aktiviert wird. Der Standardwert ist 0, was geschlossen bedeutet.
net.ipv4.tcp_fin_timeout =30#Ändern Sie die Standard-TIMEOUT-Zeit

Führen Sie dann /sbin/sysctl -p aus, damit die Parameter wirksam werden.

Einfach ausgedrückt aktiviert es die TIMEWAIT-Wiederverwendung und das schnelle Recycling des Systems.

Weitere Leistungsoptimierungen für Linux

Wenn Ihr System bereits über eine große Anzahl von Verbindungen verfügt und die Leistung nach der obigen Konfigurationsoptimierung immer noch nicht optimal ist, können Sie den verfügbaren TCP-Portbereich optimieren, um die Parallelitätsfähigkeit des Servers weiter zu verbessern. Fügen Sie noch in der Datei /etc/sysctl.conf die folgende Konfiguration hinzu:

vi /etc/sysctl.conf
#Gibt die Häufigkeit an, mit der TCP Keepalive-Nachrichten sendet, wenn Keepalive aktiviert ist. Der Standardwert ist 2 Stunden, ändern Sie ihn auf 20 Minuten.
net.ipv4.tcp_keepalive_time = 1200 
# gibt den Portbereich an, der für ausgehende Verbindungen verwendet wird. Der Standardwert ist sehr klein: 32768 bis 61000, geändert auf 1024 bis 65000.
net.ipv4.ip_local_port_range = 1024 65000 
#Gibt die Länge der SYN-Warteschlange an. Der Standardwert ist 1024. Durch Erhöhen der Warteschlangenlänge auf 8192 können mehr Netzwerkverbindungen aufgenommen werden, die auf eine Verbindung warten.
net.ipv4.tcp_max_syn_backlog = 8192 
#Gibt die maximale Anzahl von TIME_WAIT-Sockets an, die das System gleichzeitig verwaltet. Wenn diese Zahl überschritten wird, werden die TIME_WAIT-Sockets sofort gelöscht und eine Warnmeldung ausgegeben. Der Standardwert ist 180000, ändern Sie ihn auf 5000. Bei Servern wie Apache und Nginx können die Parameter in den vorherigen Zeilen die Anzahl der TIME_WAIT-Sockets effektiv reduzieren, bei Squid ist der Effekt jedoch nicht signifikant. Mit diesem Parameter kann die maximale Anzahl von TIME_WAIT-Sockets gesteuert werden, um zu verhindern, dass der Squid-Server durch eine große Anzahl von TIME_WAIT-Sockets blockiert wird.
net.ipv4.tcp_max_tw_buckets = 5000 

Weitere Anweisungen zur Optimierung der Linux-Kernelparameter

vim /etc/sysctl.conf

1. net.ipv4.tcp_max_syn_backlog = 65536

Die maximale Anzahl aufgezeichneter Verbindungsanforderungen, die noch keine Bestätigung vom Client erhalten haben. Für Systeme mit mehr als 128 MB Speicher beträgt der Standardwert 1024, und für Systeme mit weniger als 128 MB Speicher beträgt der Standardwert 128.

Bei einem SYN-Flood-Angriff werden die Handshake-Fehler des TCP-Protokolls ausgenutzt. Durch das Fälschen falscher Quell-IP-Adressen werden zahlreiche halboffene TCP-SYN-Verbindungen an das Zielsystem gesendet. Dadurch werden letztendlich die Socket-Warteschlangenressourcen des Zielsystems erschöpft und es können keine neuen Verbindungen mehr angenommen werden. Um mit dieser Art von Angriff fertig zu werden, verwenden moderne Unix-Systeme im Allgemeinen mehrere Verbindungswarteschlangen, um diese Art von Angriff abzupuffern (anstatt sie zu lösen). Eine Basiswarteschlange wird verwendet, um normale vollständig verbundene Anwendungen zu verarbeiten (Connect() und Accept()), und eine andere Warteschlange wird verwendet, um halboffene Verbindungen separat zu speichern.

Diese Dual-Queue-Verarbeitungsmethode kann in Verbindung mit einigen anderen Systemkernel-Maßnahmen (wie Syn-Cookies/Caches) kleine SYN-Flood-Angriffe (nachweislich <1000p/s) effektiv abschwächen. Durch Erhöhen der SYN-Warteschlangenlänge können mehr Netzwerkverbindungen aufgenommen werden, die auf eine Verbindung warten. Im Allgemeinen weisen Websites, die von SYN Flood angegriffen werden, eine große Anzahl von SYN_RECV-Zuständen auf, sodass das Erhöhen des tcp_max_syn_backlog-Werts die Widerstandsfähigkeit gegen SYN-Angriffe erhöhen kann.

2. net.core.netdev_max_backlog = 32768

Die maximale Anzahl von Paketen, die an die Warteschlange gesendet werden dürfen, wenn jede Netzwerkschnittstelle Pakete schneller empfängt, als der Kernel sie verarbeiten kann.

3. net.core.somaxconn = 32768

Passen Sie die Anzahl gleichzeitiger TCP-Verbindungen an, die vom System initiiert werden. Möglicherweise müssen Sie den Verbindungsreservewert erhöhen, um eine große Anzahl plötzlich eingehender Verbindungsanforderungen bewältigen zu können. Durch die Verwendung eines größeren Wertes wird die Anzahl der unterstützten ausstehenden Verbindungen erhöht. Dadurch kann die Anzahl der Verbindungsfehler verringert werden, wenn eine große Anzahl von Verbindungsanforderungen gleichzeitig empfangen wird. Eine große Listenwarteschlange kann auch dazu beitragen, DDoS-Angriffe zu verhindern. Die maximale Anzahl ausstehender Anfragen beträgt standardmäßig 128.

Zeigen Sie den Befehl zum Kernel-Paketverlust in Echtzeit an:

netstat -su

Standort: /proc/sys/

4. net.core.wmem_default = 8388608

Dieser Parameter gibt den Standardwert (in Bytes) für die Sende-Socket-Puffergröße an.

5. net.core.rmem_default = 8388608

Dieser Parameter gibt den Standardwert (in Bytes) für die Größe des Empfangs-Socket-Puffers an.

6. net.core.rmem_max = 16777216

Dieser Parameter gibt die maximale Größe des Empfangs-Socket-Puffers (in Bytes) an.

7. net.core.wmem_max = 16777216

Dieser Parameter gibt die maximale Sende-Socket-Puffergröße (in Bytes) an.

8. net.ipv4.tcp_timestamps = 0

Zeitstempel können gefälschte Sequenznummern verhindern. Bei einer 1G-Breitbandleitung kann es vorkommen, dass die alte Sequenznummer mit einem Out-of-Line-Wert erneut auftritt (sofern sie vom letzten Mal generiert wurde). Der Zeitstempel ermöglicht es dem Kernel, solche „abnormalen“ Pakete zu akzeptieren. Dies muss deaktiviert werden, um die Leistung zu verbessern.

9. net.ipv4.tcp_synack_retries = 2

Für die Remote-Verbindungsanforderung SYN sendet der Kernel ein SYN+ACK-Datagramm, um den Empfang des vorherigen SYN-Verbindungsanforderungspakets zu bestätigen. Dies ist der zweite Schritt des sogenannten Drei-Wege-Handshake-Mechanismus. Dies bestimmt die Anzahl der SYN+ACKs, die der Kernel sendet, bevor er die Verbindung aufgibt. Sollte nicht größer als 255 sein. Der Standardwert ist 5, was etwa 180 Sekunden entspricht. (Dieser Wert kann basierend auf tcp_syn_retries bestimmt werden)

10. net.ipv4.tcp_syn_retries = 2

Für eine neue Verbindung muss der Kernel eine bestimmte Anzahl von SYN-Verbindungsanforderungen senden, bevor er aufgibt. Sollte nicht größer als 255 sein. Der Standardwert ist 5, was etwa 180 Sekunden entspricht. (Für Netzwerke mit hoher Auslastung und guter physischer Kommunikation ist dieser Wert zu hoch und kann auf 2 geändert werden. Dieser Wert gilt nur für ausgehende Verbindungen. Für eingehende Verbindungen wird er durch tcp_retries1 bestimmt.)

#net.ipv4.tcp_tw_len = 1

11. net.ipv4.tcp_tw_reuse = 1

Gibt an, dass die Wiederverwendung aktiviert ist, sodass TIME-WAIT-Sockets für neue TCP-Verbindungen wiederverwendet werden können. Der Standardwert ist 0 und zeigt das Herunterfahren an. Dies ist sehr hilfreich, um bestimmte Dienste schnell neu zu starten, aber nach dem Neustart wird angezeigt, dass der Port bereits verwendet wird.

12. net.ipv4.tcp_mem = 94500000 915000000 927000000

tcp_mem hat 3 INTEGER-Variablen: low, pressure, high

niedrig: Wenn TCP weniger als diesen Wert an Speicherseiten verwendet, hat TCP keinen Speicherdruck und erwägt nicht, Speicher freizugeben. (Idealerweise sollte dieser Wert mit dem zweiten für tcp_wmem angegebenen Wert übereinstimmen. Dieser zweite Wert gibt die maximale Seitengröße multipliziert mit der maximalen Anzahl gleichzeitiger Anfragen geteilt durch die Seitengröße an (131072*300/4096).

Druck: Wenn TCP mehr als diesen Wert an Speicherseiten verwendet, versucht TCP, seine Speichernutzung zu stabilisieren und wechselt in den Druckmodus. Wenn der Speicherverbrauch unter den niedrigen Wert fällt, wird der Druckzustand beendet. (Idealerweise sollte dieser Wert dem Maximalwert der gesamten Puffergröße entsprechen, die TCP verwenden kann (204800*300/4096)

Hoch: Die für alle TCP-Sockets zulässige Seitenanzahl zum Warteschlangen- und Puffern von Datagrammen. Bei Überschreitung dieses Wertes wird die TCP-Verbindung abgelehnt, weshalb ein zu konservativer Wert (512000*300/4096) nicht ratsam ist. In diesem Fall ist der bereitgestellte Wert enorm, da 2,5-mal mehr Verbindungen als erwartet verarbeitet werden können oder bestehende Verbindungen die Übertragung von 2,5-mal mehr Daten ermöglichen können.

Normalerweise werden diese Werte beim Systemstart basierend auf der Menge des Systemspeichers berechnet.

13. net.ipv4.tcp_max_orphans = 3276800

Die maximale Anzahl von TCP-Sockets, die das System verarbeiten kann und die keinem Prozess gehören. Wird diese Zahl überschritten, werden Verbindungen, die keinem Prozess angehören, sofort zurückgesetzt und eine Warnmeldung angezeigt. Der Grund für die Festlegung dieses Grenzwertes ist lediglich der Schutz vor einfachen DoS-Angriffen. Verlassen Sie sich nicht darauf und senken Sie diesen Grenzwert nicht künstlich ab.

14. net.ipv4.tcp_fin_timeout = 30

Wenn der Socket vom lokalen Ende geschlossen wird, bestimmt dieser Parameter, wie lange er im Zustand FIN-WAIT-2 bleibt. Dem Peer können Fehler unterlaufen und die Verbindung nie schließen oder sogar unerwartet abstürzen. Der Standardwert beträgt 60 Sekunden. Der übliche Wert für 2.2-Kernel beträgt 180 Sekunden. Sie können ihn auf diese Weise einstellen, aber denken Sie daran, dass selbst wenn Ihr Rechner ein leicht ausgelasteter Webserver ist, aufgrund einer großen Anzahl toter Sockets die Gefahr eines Speicherüberlaufs besteht. FIN-WAIT-2 ist weniger gefährlich als FIN-WAIT-1, da es nur bis zu 1,5 KB Speicher verbrauchen kann, aber seine Lebensdauer ist länger.

15. net.ipv4.ip_conntrack_max = 10000

Legen Sie die maximale Systemgrenze für die Anzahl der verfolgten TCP-Verbindungen fest (CentOS 5.6 verfügt nicht über diesen Parameter).

Es handelt sich auch um ein Problem mit dem TCP-Überlastungsalgorithmus. Mit dem folgenden Befehl können Sie das von dieser Maschine bereitgestellte Kontrollmodul für den Überlastungsalgorithmus anzeigen:

sysctlnet.ipv4.tcp_verfügbare_Überlastungskontrolle

Einzelheiten zur Analyse mehrerer Algorithmen finden Sie im Folgenden: Vorteile und Nachteile, anwendbare Umgebung und Leistungsanalyse von TCP-Überlastungskontrollalgorithmen. Beispielsweise kann Hybla für hohe Latenz und der HTCP-Algorithmus für mittlere Latenz ausprobiert werden.

Wenn Sie den TCP-Überlastungsalgorithmus auf hybla setzen möchten

#TCP-Überlastungsalgorithmus festlegen net.ipv4.tcp_congestion_control=hybla

Für Kernelversionen höher als 3.7.1 können wir tcp_fastopen aktivieren:

# Aktivieren Sie tcp_fastopen
net.ipv4.tcp_fastopen = 3

Iptables bezogen

Wenn dies nicht erforderlich ist, schalten Sie die iptables-Firewall aus oder deinstallieren Sie sie und verhindern Sie, dass der Kernel das iptables-Modul lädt. Diese Module beeinträchtigen die Parallelitätsleistung.

IO-Ereigniszuweisungsmechanismus

Um eine hohe Anzahl gleichzeitiger TCP-Verbindungen in Linux zu ermöglichen, müssen Sie bestätigen, dass die Anwendung die entsprechende Netzwerk-E/A-Technologie und den entsprechenden Mechanismus zur E/A-Ereignisverteilung verwendet. Die verfügbaren E/A-Technologien sind synchrone E/A, nicht blockierende synchrone E/A und asynchrone E/A. Bei hoher TCP-Parallelität wird die Ausführung des Programms bei Verwendung synchroner E/A ernsthaft blockiert, sofern nicht für die E/A jeder TCP-Verbindung ein Thread erstellt wird. Zu viele Threads verursachen jedoch aufgrund der Thread-Planung des Systems einen enormen Overhead. Daher ist es nicht ratsam, bei hoher TCP-Parallelität synchrone E/A zu verwenden. Zu diesem Zeitpunkt können Sie die Verwendung von nicht blockierender synchroner E/A oder asynchroner E/A in Betracht ziehen. Zu den nicht blockierenden synchronen E/A-Techniken gehören die Verwendung von select(), poll(), epoll und anderen Mechanismen. Die Technologie für asynchronen E/A besteht in der Verwendung von AIO.

Aus Sicht des Mechanismus zur E/A-Ereignisverteilung ist die Verwendung von select() ungeeignet, da die Anzahl der unterstützten gleichzeitigen Verbindungen begrenzt ist (normalerweise auf 1024 begrenzt). Wenn man die Leistung betrachtet, ist poll() auch nicht geeignet. Obwohl es eine höhere Anzahl von TCP-Parallelverbindungen unterstützen kann, verwendet es einen „Polling“-Mechanismus. Bei einer hohen Anzahl von Parallelverbindungen ist seine Betriebseffizienz ziemlich gering und es kann zu einer ungleichmäßigen Verteilung der E/A-Ereignisse kommen, was zu einem „Verhungern“ der E/A bei einigen TCP-Verbindungen führt. Bei Verwendung von Epoll oder AIO treten derartige Probleme nicht auf (die AIO-Technologie der frühen Linux-Kernel wurde implementiert, indem für jede E/A-Anforderung ein Thread im Kernel erstellt wurde. Dieser Implementierungsmechanismus weist tatsächlich schwerwiegende Leistungsprobleme auf, wenn er bei TCP-Verbindungen mit hoher Parallelität verwendet wird. Im neuesten Linux-Kernel wurde die AIO-Implementierung jedoch verbessert).

Zusammenfassung

Zusammenfassend lässt sich sagen, dass Sie bei der Entwicklung von Linux-Anwendungen, die hoch parallele TCP-Verbindungen unterstützen, versuchen sollten, die Epoll- oder AIO-Technologie zu verwenden, um die E/A-Steuerung für gleichzeitige TCP-Verbindungen zu implementieren. Dadurch erhalten Sie effektive E/A-Garantien, um die Unterstützung des Programms für hoch parallele TCP-Verbindungen zu verbessern.

Nach der oben beschriebenen Optimierungskonfiguration wird die TCP-Parallelverarbeitungskapazität des Servers deutlich verbessert. Die oben beschriebene Konfiguration dient nur als Referenz. Bei Verwendung in einer Produktionsumgebung passen Sie sie bitte entsprechend der tatsächlichen Situation Ihrer eigenen Entwicklungssystembereitstellung an und beachten Sie sie.

Dies ist das Ende dieses Artikels über die Fallstricke der hohen Parallelität und Leistungsoptimierung unter Linux. Weitere relevante Inhalte zur hohen Parallelität und Leistungsoptimierung unter Linux finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den verwandten Artikeln weiter unten. Ich hoffe, dass jeder 123WORDPRESS.COM in Zukunft unterstützen wird!

Das könnte Sie auch interessieren:
  • Erläuterung der Linux-Kernel-Optimierungskonfiguration für hochparallele Nginx-Server
  • Detaillierte Erläuterung zur Optimierung der maximalen Anzahl gleichzeitiger Socket-Verbindungen in Linux

<<:  Detaillierte Erklärung zum Erstellen gespeicherter Prozeduren und Funktionen in MySQL

>>:  CSS-Rahmen fügt Implementierungscode für vier Ecken hinzu

Artikel empfehlen

Detaillierte Erklärung der berechneten Eigenschaften von Vue

1. Was ist ein berechnetes Attribut? Einfach ausg...

Grafisches Tutorial zur Installation und Konfiguration von MySQL 8.0.19

In diesem Artikel wird das grafische Tutorial zur...

So erweitern Sie Vue Router-Links in Vue 3

Vorwort Das Tag <router-link> ist ein großa...

CSS3-Animation – Erläuterung der Funktion „Steps“

Als ich mir in letzter Zeit einige CSS3-Animation...

Lösung für den MySQL-Server-Anmeldefehler ERROR 1820 (HY000)

Fehlerseite: Melden Sie sich beim MySQL-Server an...

So importieren Sie CSS-Stile in externe HTML-Stylesheets

Der Link-In-Stil besteht darin, alle Stile in ein...

Erklärung der Rückgabe einer MySQL-Tabelle führt zur Ungültigkeit des Index

Einführung Wenn die MySQL InnoDB-Engine Datensätz...

Erfahrungsaustausch zur Reparatur von MySQL InnoDB-Ausnahmen

Eine Reihe von MySQL-Bibliotheken zum Testen. Die...

Neulinge lernen schnell die Schritte zum Erstellen von Website-Symbolen

<br />Original-URL: http://www.lxdong.com/po...