Grüße Freunde!
In den beiden vorhergehenden Artikeln (
eins ,
zwei ) haben wir uns mit der Komplexität der Wahl zwischen Technologien befasst und in
Ostrovok.ru nach den optimalen Einstellungen für unsere Lösung
gesucht . Welches Thema werden wir heute ansprechen?
Jeder Dienst sollte auf einem Server funktionieren und über die Tools des Betriebssystems mit der Hardware kommunizieren. Es gibt sehr viele dieser Tools sowie Einstellungen für sie. In den meisten Fällen sind ihre Standardeinstellungen mehr als ausreichend. In diesem Artikel möchte ich über jene Fälle sprechen, in denen die Standardeinstellungen noch nicht ausreichten und ich das Betriebssystem etwas näher kennenlernen musste - in unserem Fall mit
Linux .

Wir setzen Kernel mit Bedacht ein
In einem
früheren Artikel habe ich über die
Option CPU-Map in
Haproxy gesprochen . Damit binden wir Haproxy-Prozesse an Threads eines Kerns auf einem Dual-Prozessor-Server. Wir haben den zweiten Kern für die Interrupt-Behandlung von Netzwerkkarten gegeben.
Unten sehen Sie einen Bildschirm, auf dem Sie eine ähnliche Trennung sehen können. Links werden die Kernel von Haproxy im
user space
, und rechts werden Interrupts im Kernelbereich verarbeitet.

Das Binden von Interrupts an eine Netzwerkkarte erfolgt automatisch damit
Es gibt viele geeignete einfache und komplexere Skripte im Internet, die dieselbe Aufgabe erfüllen, aber dieses Skript reicht für unsere Anforderungen aus.
Bei Haproxy haben wir Prozesse mit Kerneln verknüpft, beginnend mit dem ersten Kernel. Das gleiche Skript bindet Interrupts, beginnend mit dem letzten. Somit können wir die Serverprozessoren in zwei Lager aufteilen.
Für einen tieferen Einblick in Unterbrechungen und Vernetzung empfehle ich dringend, diesen
Artikel zu lesen.
Wir zeigen die Fähigkeiten von Netzwerkgeräten
Es kommt vor, dass sehr viele Frames gleichzeitig über das Netzwerk fliegen können und die Kartenwarteschlange möglicherweise nicht für einen solchen Zustrom von Gästen bereit ist, selbst wenn sie die Möglichkeit dazu hat.
Lassen Sie uns über den Netzwerkkartenpuffer sprechen. In den meisten Fällen verwenden die Standardwerte nicht den gesamten verfügbaren Puffer. Sie können die aktuellen Einstellungen mit dem leistungsstarken Dienstprogramm ethtool anzeigen.
Beispiel für die Verwendung von Befehlen:
> ethtool -g eno1 Ring parameters for eno1: Pre-set maximums: RX: 4096 RX Mini: 0 RX Jumbo: 0 TX: 4096 Current hardware settings: RX: 256 RX Mini: 0 RX Jumbo: 0 TX: 256
Nehmen wir jetzt alles aus dem Leben:
> ethtool -G eno1 rx 4096 tx 4096 > ethtool -g eno1 Ring parameters for eno1: Pre-set maximums: RX: 4096 RX Mini: 0 RX Jumbo: 0 TX: 4096 Current hardware settings: RX: 4096 RX Mini: 0 RX Jumbo: 0 TX: 4096
Jetzt können Sie sicher sein, dass die Karte nicht zurückgehalten wird und maximal funktioniert.
Minimale Systemeinstellungen für maximalen Nutzen
Sysctl bietet eine Vielzahl von Optionen in allen erdenklichen Farben und Größen. In der Regel decken Artikel im Internet, die sich mit dem Thema Optimierung befassen, einen ziemlich beeindruckenden Teil dieser Parameter ab. Ich werde nur diejenigen betrachten, die in unserem Fall wirklich nützlich waren, um sie zu ändern.
net.core.netdev_max_backlog - die Warteschlange, in der Frames von der Netzwerkkarte
abgerufen werden , die dann vom Kernel verarbeitet werden. Mit schnellen Schnittstellen und viel Verkehr kann es schnell voll werden.
Standard : 1000.
Wir können den Überschuss dieser Warteschlange beobachten, indem wir uns die zweite Spalte in der Datei / proc / net / softnet_stat ansehen.
awk '{print $2}' /proc/net/softnet_stat
Die Datei selbst beschreibt die Struktur von
netif_rx_stats pro Zeile für jede CPU im System.
Insbesondere beschreibt die zweite Spalte die Anzahl der Pakete im verworfenen Zustand. Wenn der Wert in der zweiten Spalte mit der Zeit wächst, lohnt es sich wahrscheinlich, den Wert von
net.core.netdev_max_backlog
oder die CPU schneller zu machen.
net.core.rmem_default /
net.core.rmem_max &&
net.core.wmem_default /
net.core.wmem_max - Diese Parameter geben den Standardwert / Maximalwert für Socket-Lese- und Schreibpuffer an.
Der Standardwert kann auf Anwendungsebene zum Zeitpunkt der Erstellung des Sockets geändert werden (Haproxy verfügt übrigens über einen
Parameter , der dies ausführt). Wir hatten Fälle, in denen der Kernel mehr Pakete warf, als Haproxy harken konnte, und dann begannen die Probleme. Daher ist die Sache wichtig.
net.ipv4.tcp_max_syn_backlog - ist verantwortlich für die Begrenzung neuer Verbindungen, für die noch kein
SYN
Paket empfangen wurde. Wenn es einen großen Strom neuer Verbindungen gibt (z. B. viele HTTP-Anforderungen von
Connection: close
), ist es sinnvoll, diesen Wert zu erhöhen, um keine Zeit mit dem Senden weitergeleiteter Pakete zu verschwenden.
net.core.somaxconn - hier handelt es sich um hergestellte Verbindungen, die jedoch noch nicht von der Anwendung verarbeitet wurden. Wenn der Server Single-Threaded ist und zwei Anforderungen eingegangen sind, wird die erste Anforderung von der Funktion
accept()
, und die zweite hängt im
backlog
, dessen Größe für diesen Parameter verantwortlich ist.
nf_conntrack_max ist wahrscheinlich der bekannteste aller Parameter. Ich denke, fast jeder, der sich mit Iptables befasst hat, weiß davon. Im Idealfall können Sie das Conntrack-Modul natürlich entladen und nicht darüber nachdenken, wenn Sie keine Maskierung für iptables verwenden müssen. In meinem Fall wird
Docker verwendet, sodass Sie nichts Besonderes hochladen.
Überwachung Offensichtlich und nicht sehr
Um nicht blind zu suchen, warum "Ihr Proxy langsamer wird", ist es hilfreich, einige Diagramme einzurichten und sie mit Triggern zu überlagern.
nf_conntrack_count ist die offensichtlichste Metrik. Darauf können Sie überwachen, wie viele Verbindungen sich jetzt in der
Conntrack-Tabelle befinden . Wenn die Tabelle überläuft, wird der Pfad für neue Verbindungen geschlossen.
Den aktuellen Wert finden Sie hier:
cat /proc/sys/net/netfilter/nf_conntrack_count
Tcp-Segmente erneut übertragen - die Anzahl der
Segmentübertragungen . Die Metrik ist sehr umfangreich, da sie über Probleme auf verschiedenen Ebenen sprechen kann. Die Zunahme der Übertragungen kann auf Netzwerkprobleme, die Notwendigkeit einer Optimierung der Systemeinstellungen oder sogar darauf hinweisen, dass die endgültige Software (z. B. Haproxy) ihre Aufgabe nicht erfüllt. Wie dem auch sei, das abnormale Wachstum dieses Wertes kann als Grund für ein Verfahren dienen.

In unserem Land weist eine Wertsteigerung am häufigsten auf Probleme mit einem der Lieferanten hin, obwohl es Probleme mit der Leistung sowohl der Server als auch des Netzwerks gab.
Beispiel zur Überprüfung:
netstat -s|grep 'segments retransmited'
Socket Recv-Q -
Denken Sie daran, wir haben über Momente gesprochen, in denen eine Anwendung möglicherweise nicht genügend Zeit hat, um Anforderungen zu verarbeiten, und dann der
socket backlog
wächst. Das Wachstum dieses Indikators macht deutlich, dass etwas mit der Anwendung nicht stimmt und nicht bewältigt werden kann.
Ich habe Berge in Diagrammen mit dieser Metrik gesehen, als der Parameter maxconn in Haproxy einen Standardwert (2000) hatte und einfach keine neuen Verbindungen akzeptierte.
Und noch einmal ein Beispiel:
ss -lntp|awk '/LISTEN/ {print $2}'

Es ist nicht überflüssig, ein Diagramm mit einer Aufschlüsselung nach Status der TCP-Verbindungen zu haben:

Und separat machen
time-wait/established
, weil Ihre Werte unterscheiden sich in der Regel stark von den anderen:

Zusätzlich zu diesen Metriken gibt es viele andere, aber offensichtlichere - zum Beispiel die Belastung der Netzwerkschnittstelle oder der CPU. Ihre Wahl hängt bereits mehr von den Besonderheiten Ihrer Arbeitsbelastung ab.
Anstelle einer Schlussfolgerung
Im Allgemeinen ist das alles - ich habe versucht, die wichtigsten Punkte zu beschreiben, denen ich beim Einrichten des http-Reverse-Proxys begegnen musste. Es scheint, dass die Aufgabe nicht schwierig ist, aber mit zunehmender Last steigt auch die Anzahl der Fallstricke, die immer zur falschen Zeit auftauchen. Ich hoffe, dieser Artikel hilft Ihnen, die Schwierigkeiten zu vermeiden, mit denen ich konfrontiert war.
Aller Frieden