Optimierung des Linux-Netzwerkdurchsatzes durch Anpassung von TCP/IP-sysctl-Parametern

Praktische Linux-TCP-sysctl-Optimierung für Durchsatz, Puffer, Überlastungskontrolle und sicheres Testen.

Optimierung des Linux-Netzwerkdurchsatzes durch Anpassung von TCP/IP-sysctl-Parametern

Die Optimierung des Linux-Netzwerkdurchsatzes beginnt mit einer langweiligen Frage: Was ist eigentlich langsam? Ein Server, der auf einer 10-Gbit/s-Verbindung maximal 300 Mbit/s erreicht, könnte ein TCP-Fensterproblem, ein Festplattenproblem, ein CPU-Interrupt-Problem, eine schlechte virtuelle NIC-Einstellung, ein Paketverlustproblem oder eine Anwendung haben, die Daten in winzigen Stücken sendet. Die sysctl-Optimierung hilft nur bei einigen davon.

Deshalb behandle ich TCP/IP-sysctl-Änderungen als kontrollierte Experimente, nicht als magische Leistungsrezepte. Beginnen Sie mit einer Basislinie, ändern Sie eine kleine Gruppe von Einstellungen, testen Sie erneut und machen Sie sich Notizen. Wenn Sie einen riesigen Optimierungsblock aus dem Internet in /etc/sysctl.conf kopieren, verbessern Sie möglicherweise eine Arbeitslast und beeinträchtigen leise eine andere.

Die folgenden Einstellungen sind nützlich, wenn Sie Dienste mit hohem Durchsatz betreiben: Artefakt-Repositories, Backup-Server, Objektspeicher-Gateways, ausgelastete Reverse-Proxys, Datenbankreplikate, die große Protokolle versenden, oder Linux-Hosts, die Datenverkehr über große Entfernungen bewegen. Sie helfen weniger, wenn Ihr Engpass die TLS-Verschlüsselungs-CPU, langsamer Speicher, Anwendungssperren, Cloud-Anbieterlimits oder Paketverluste außerhalb des Hosts sind.

Sammeln Sie vor jeder Änderung eine schnelle Basislinie:

ip -s link
ss -s
nstat -az | egrep 'TcpRetransSegs|TcpExtTCPLoss|TcpExtTCPTimeouts|TcpExtListenOverflows'
sar -n DEV,TCP,ETCP 1 10
iperf3 -c test-host -P 4 -t 30

Wenn Sie sehen, dass Wiederholungen ansteigen, beheben Sie zuerst den Verlust, bevor Sie die Puffer erhöhen. Wenn die CPU bereits in top, mpstat oder perf ausgelastet ist, können sysctls das Symptom verbergen, aber nicht den Engpass beseitigen. Wenn iperf3 schnell ist, Ihre Anwendung jedoch langsam, schauen Sie sich den Anwendungspfad an, bevor Sie den Kernel optimieren.

Wie sysctl in die Netzwerkoptimierung passt

sysctl macht Kernel-Parameter während des Systembetriebs zugänglich. Netzwerkeinstellungen befinden sich normalerweise unter net.ipv4, net.ipv6 und net.core. Sie können einen Wert wie folgt lesen:

sysctl net.ipv4.tcp_congestion_control
sysctl net.ipv4.tcp_rmem
sysctl net.core.rmem_max

Sie können eine temporäre Änderung wie folgt testen:

sudo sysctl -w net.ipv4.tcp_congestion_control=bbr

Temporäre Änderungen verschwinden nach einem Neustart. Dauerhafte Änderungen gehören in eine dedizierte Datei wie /etc/sysctl.d/90-network-throughput.conf, nicht verstreut in /etc/sysctl.conf ohne Erklärung.

sudo install -m 0644 /dev/null /etc/sysctl.d/90-network-throughput.conf
sudo editor /etc/sysctl.d/90-network-throughput.conf
sudo sysctl --system

Verwenden Sie eine separate Datei, da der Rollback einfach ist: Verschieben Sie die Datei und führen Sie erneut sudo sysctl --system aus. Das ist wichtig, wenn sich eine Einstellung unter Produktionslast schlecht verhält.

TCP-Puffer: Geben Sie langen Verbindungen Raum zum Atmen

Der erste Ort, an den Leute schauen, ist die Puffergröße. TCP benötigt ausreichend Sende- und Empfangsfensterplatz, um Daten während der Übertragung zu halten, während Bestätigungen über das Netzwerk reisen. Das nützliche mentale Modell ist das Bandbreiten-Verzögerungs-Produkt: Eine Verbindung mit hoher Bandbreite und hoher Latenz benötigt mehr ausstehende Daten als eine LAN-Verbindung mit niedriger Latenz.

Beispielsweise benötigt eine 1-Gbit/s-Übertragung über einen 1-ms-Rechenzentrumspfad weit weniger Daten während der Übertragung als eine 1-Gbit/s-Übertragung über einen 70-ms-WAN-Pfad. Wenn das Empfangsfenster zu klein ist, pausiert der Sender, obwohl die Verbindung Platz hat.

Linux verwendet Dreiwert-Arrays für die TCP-Speicheroptimierung:

net.ipv4.tcp_rmem = 4096 131072 33554432
net.ipv4.tcp_wmem = 4096 131072 33554432

Die drei Zahlen sind die minimale, standardmäßige und maximale Puffergröße pro Socket in Bytes. Die genauen Werte sollten zu Ihrer Arbeitslast, Ihrem Speicherbudget und dem Kernelverhalten passen. Das obige Beispiel erhöht das Maximum auf 32 MiB, was für ausgelastete Server oft ausreicht, ohne rücksichtslos zu sein. Einige Systeme mit großer Reichweite oder speicherintensiven Systemen verwenden größere Werte, aber das sollte mit echtem Datenverkehr getestet werden.

Die net.core-Grenzen begrenzen Socket-Puffer:

net.core.rmem_max = 33554432
net.core.wmem_max = 33554432

Wenn tcp_rmem besagt, dass TCP auf 32 MiB anwachsen kann, aber net.core.rmem_max viel niedriger ist, gewinnt in der Praxis die niedrigere Grenze. Halten Sie die Grenzen mit den TCP-Maxima übereinstimmend, es sei denn, Sie haben einen Grund dagegen.

Erhöhen Sie die Puffer nicht blind auf einem Rechner mit vielen gleichzeitigen Verbindungen. Ein Dateiserver mit wenigen großen Datenströmen kann sich größere Puffer pro Datenstrom leisten. Ein Proxy, der Hunderttausende von Verbindungen verarbeitet, kann schnell Speicher verbrauchen, wenn Sie jeden Socket für riesige Puffer qualifizieren.

Die automatische Optimierung leistet bereits etwas Arbeit

Moderne Linux-Kernel optimieren TCP-Puffer bereits automatisch. Das bedeutet, dass Sie normalerweise keine großen festen Socket-Puffer in der Anwendung setzen müssen. Der Kernel vergrößert die Puffer, wenn eine Verbindung von mehr Platz profitiert.

Ihre Aufgabe besteht hauptsächlich darin, sicherzustellen, dass die Obergrenze nicht zu niedrig ist. Wenn der Durchsatz auf einem langen, dicken Netzwerk schlecht ist und ss -tin kleine Empfangsfenster oder einen durch den Empfänger blockierten Sender zeigt, kann das Erhöhen von tcp_rmem, tcp_wmem, rmem_max und wmem_max helfen.

Überprüfen Sie aktive Verbindungen mit:

ss -tin dst <peer-ip>

Achten Sie auf Felder wie cwnd, rtt, rto, bytes_acked, bytes_received und Wiederholungszähler. Sie erzählen eine bessere Geschichte als ein einzelner Geschwindigkeitstest.

Überlastungskontrolle: CUBIC, BBR und die Realität

Der Überlastungskontrollalgorithmus entscheidet, wie TCP seine Senderate erhöht oder verringert. Auf vielen Linux-Systemen ist CUBIC die Standardeinstellung und funktioniert gut für allgemeinen Internet- und Rechenzentrumsverkehr. BBR kann den Durchsatz und die Latenz auf einigen verlustbehafteten oder Langstreckenpfaden verbessern, da es die Engpassbandbreite und die Round-Trip-Zeit modelliert, anstatt nur auf Paketverluste zu reagieren.

Überprüfen Sie verfügbare Algorithmen:

sysctl net.ipv4.tcp_available_congestion_control
sysctl net.ipv4.tcp_congestion_control

Aktivieren Sie BBR nur, wenn Ihr Kernel es verfügbar hat:

sudo sysctl -w net.ipv4.tcp_congestion_control=bbr

Für die Persistenz:

net.ipv4.tcp_congestion_control = bbr

Einige Systeme benötigen auch den Fair-Queuing-Paketplaner für ein gutes BBR-Verhalten:

net.core.default_qdisc = fq

Gehen Sie nicht davon aus, dass BBR immer schneller ist. Es kann die Fairness mit anderen Datenströmen verändern, und verschiedene BBR-Versionen verhalten sich auf verschiedenen Kerneln unterschiedlich. Testen Sie es mit dem gleichen Verkehrsmuster, das Ihnen wichtig ist: viele kleine API-Aufrufe, einige wenige Massenübertragungen, replizierter Datenbankverkehr oder gemischte produktionsähnliche Last.

Warteschlangen für eingehende Verbindungen: Beheben Sie Verluste, bevor sie zu Rätseln werden

Durchsatzprobleme zeigen sich manchmal als Verbindungsfehler während Verkehrsspitzen. Wenn ein Dienst neue TCP-Verbindungen langsamer akzeptiert, als Clients sie erstellen, füllen sich die Kernel-Warteschlangen.

Relevante Einstellungen:

net.core.somaxconn = 4096
net.ipv4.tcp_max_syn_backlog = 8192

somaxconn begrenzt den von Anwendungen über listen(2) angeforderten Rückstand abgeschlossener Verbindungen. tcp_max_syn_backlog beeinflusst die Kapazität der halboffenen SYN-Warteschlange. Das Erhöhen kann ausgelasteten Webservern, Proxys und Lastverteilern helfen, aber die Anwendung muss auch einen ausreichend großen Rückstand anfordern. Nginx, HAProxy, Envoy und Anwendungsserver haben oft ihre eigenen Rückstandseinstellungen.

Achten Sie auf Überläufe:

nstat -az | egrep 'ListenOverflows|ListenDrops|Syncookies'
ss -ltn

Wenn ListenOverflows ansteigt, halten die Kernel-Warteschlangen nicht Schritt. Wenn die CPU ausgelastet ist oder die App durch nachgelagerte Dienste blockiert wird, kann eine Vergrößerung der Warteschlangen die Client-Fehler vorübergehend reduzieren, aber den Dienst nicht reparieren.

Rückstand und Paketverarbeitung

net.core.netdev_max_backlog steuert, wie viele Pakete in der Eingangswarteschlange warten können, wenn der Kernel Pakete schneller empfängt, als er sie verarbeiten kann.

net.core.netdev_max_backlog = 250000

Dies kann auf Hochgeschwindigkeitsschnittstellen während Bursts helfen, insbesondere bei virtualisierter Vernetzung. Es kann auch die Latenz erhöhen, wenn Sie den Host in einen großen Paketwartesaal verwandeln. Überprüfen Sie zuerst die Schnittstellenverluste:

ip -s link show dev eth0
ethtool -S eth0 | egrep 'drop|err|timeout|miss|fifo'

Wenn Verluste auf Treiberebene ansteigen, überprüfen Sie auch die NIC-Ringgrößen, die Interrupt-Verteilung, RSS-Warteschlangen und die CPU-Affinität. Diese liegen außerhalb von sysctl, sind aber oft wichtiger als TCP-Puffer auf 10-Gbit/s- und schnelleren Hosts.

TIME_WAIT und Port-Erschöpfung

Hochdurchsatz-Clients, Proxys und Job-Runner können möglicherweise keine ephemeren Ports mehr haben oder viele Sockets im Zustand TIME_WAIT ansammeln. Seien Sie hier vorsichtig, da alte Optimierungsratschläge schädlich sein können.

Überprüfen Sie den aktuellen Bereich:

sysctl net.ipv4.ip_local_port_range
ss -tan state time-wait | wc -l

Eine vernünftige clientseitige Anpassung ist die Erweiterung des ephemeren Portbereichs:

net.ipv4.ip_local_port_range = 10240 60999

Vermeiden Sie alte Ratschläge, die tcp_tw_recycle empfehlen; es wurde aus Linux entfernt, weil es gültigen Datenverkehr störte, insbesondere hinter NAT. tcp_tw_reuse existiert auf vielen Kerneln, aber sein Verhalten hat sich im Laufe der Zeit geändert. Aktivieren Sie es nicht als Standard-Durchsatzeinstellung. Wenn Sie glauben, dass Sie es brauchen, testen Sie es sorgfältig mit Ihrem genauen Kernel und Verkehrsmuster.

Für Server ist ein Haufen TIME_WAIT-Sockets oft normal. Für Clients bedeutet Port-Erschöpfung normalerweise, dass Sie Verbindungspooling, Keep-Alive, HTTP/2, weniger kurzlebige ausgehende Verbindungen oder mehr Quell-IPs benötigen.

Eine konservative Startdatei

Hier ist ein praktischer Ausgangspunkt für einen Hochdurchsatz-Server. Er ist bewusst nicht extrem:

# /etc/sysctl.d/90-network-throughput.conf

# Größere TCP-Autotuning-Obergrenzen für Pfade mit hoher Bandbreite oder höherer Latenz.
net.core.rmem_max = 33554432
net.core.wmem_max = 33554432
net.ipv4.tcp_rmem = 4096 131072 33554432
net.ipv4.tcp_wmem = 4096 131072 33554432

# Größere Warteschlangen für burstigen eingehenden Datenverkehr.
net.core.somaxconn = 4096
net.ipv4.tcp_max_syn_backlog = 8192
net.core.netdev_max_backlog = 250000

# Optional: vor der globalen Aktivierung testen.
# net.core.default_qdisc = fq
# net.ipv4.tcp_congestion_control = bbr

Anwenden:

sudo sysctl --system

Dann erneut messen. Verwenden Sie die gleiche Testgröße, das gleiche Zeitfenster, die gleiche Anzahl paralleler Datenströme und den gleichen Netzwerkpfad. Ein Vorher-Nachher-Test, der fünf Variablen ändert, ist kein Beweis.

Häufige Fehler

Der erste Fehler ist die Optimierung auf einem verlustbehafteten Pfad. TCP betrachtet Verlust als Überlastung. Größere Puffer können den Durchsatz etwas erhöhen, aber sie können auch die Latenz erhöhen und das eigentliche Problem verbergen. Beheben Sie zuerst defekte Kabel, überlastete virtuelle Switches, Paket-Policing, MTU-Inkonsistenzen und instabile VPN-Pfade.

Der zweite Fehler ist die Annahme, dass iperf3 -P 8 die Anwendungsleistung beweist. Parallele Datenströme können eine Verbindung füllen, selbst wenn eine einzelne echte Anwendungsverbindung dies nicht kann. Das sind nützliche Informationen, aber nicht die ganze Geschichte.

Der dritte Fehler ist das Setzen enormer Puffer auf gemeinsam genutzten Hosts. Größere Obergrenzen sind in Ordnung, wenn der Kernel Puffer nur nach Bedarf vergrößert, aber der Speicherdruck ändert alles. Überwachen Sie free, slabtop, TCP-Speicher und Anwendungsspeicher nach Änderungen.

Der vierte Fehler ist das Vergessen des Rollbacks. Bewahren Sie die vorherigen Werte in Ihrem Änderungsticket oder Runbook auf:

sysctl -a | egrep 'net.core.rmem_max|net.core.wmem_max|net.ipv4.tcp_rmem|net.ipv4.tcp_wmem|net.ipv4.tcp_congestion_control'

Wenn sysctl nicht die Lösung ist

Wenn ein CPU-Kern ausgelastet ist, während andere im Leerlauf sind, schauen Sie sich die Interrupt-Behandlung, RSS, RPS/XPS und die Anwendungsthreadverwaltung an. Wenn die Festplattenwartezeit hoch ist, wartet das Netzwerk möglicherweise auf den Speicher. Wenn TLS die CPU verbraucht, testen Sie mit und ohne Verschlüsselung und ziehen Sie Hardware, Chiffre-Auswahl oder Verbindungswiederverwendung in Betracht. Wenn Kubernetes oder ein Cloud-Lastverteiler im Pfad sitzt, überprüfen Sie dienstseitige Grenzen und Conntrack-Tabellen.

Für NAT-lastige Hosts überprüfen Sie auch Conntrack:

sysctl net.netfilter.nf_conntrack_count
sysctl net.netfilter.nf_conntrack_max

Das ist keine TCP-Durchsatzoptimierung, aber Conntrack-Erschöpfung kann wie zufällige Netzwerklangsamkeit oder abgebrochene Verbindungen aussehen.

Testen, ohne sich selbst zu täuschen

Verwenden Sie iperf3 als Netzwerkwerkzeug, nicht als Beweis dafür, dass die Anwendung repariert ist. Ein Einzelstromtest ist nützlich, weil er zeigt, was eine einzelne TCP-Verbindung leisten kann:

iperf3 -c test-host -t 30

Ein paralleler Test zeigt, ob die Verbindung durch mehrere Datenströme gefüllt werden kann:

iperf3 -c test-host -P 8 -t 30

Wenn parallele Datenströme schnell sind, aber ein einzelner Datenstrom langsam ist, schauen Sie sich die Überlastungskontrolle, das TCP-Fensterwachstum, RTT und Paketverluste an. Wenn beide langsam sind, schauen Sie tiefer: Schnittstellenfehler, Cloud-Bandbreitenlimits, CPU-Auslastung, MTU, Firewall-Inspektion oder Speicher hinter Sender und Empfänger.

Halten Sie den Testpfad realistisch. Das Testen von zwei Hosts im selben Rack wird Ihnen nicht viel über einen Backup-Job über Regionen hinweg sagen. Das Testen mit einer winzigen Datei wird den stationären Durchsatz nicht offenlegen. Das Testen über ein VPN misst möglicherweise eher das VPN-Gerät als Linux TCP.

Erfassen Sie nach jeder Änderung die gleichen Zähler:

nstat -az > /tmp/nstat-after.txt
ss -s
sar -n DEV,TCP,ETCP 1 10

Das nützliche Ergebnis ist nicht nur "die Zahl ist gestiegen". Sie möchten wissen, ob Wiederholungen zurückgegangen sind, Warteschlangen nicht mehr überlaufen, die CPU vernünftig geblieben ist und die Latenz für kleinere Anfragen nicht schlechter geworden ist.

Gute Linux-Netzwerkoptimierung ist gemessen und umkehrbar. Erhöhen Sie die TCP-Pufferobergrenzen, wenn der Pfad größere Fenster benötigt. Testen Sie die Überlastungskontrolle, anstatt anzunehmen, dass ein Algorithmus überall gewinnt. Erhöhen Sie die Warteschlangen für eingehende Verbindungen, wenn Sie Warteschlangenverluste sehen, und reparieren Sie die Anwendung, wenn sie nicht schnell genug akzeptieren kann. sysctl ist nützlich, aber es ist eine Schicht in einem größeren System.