Optimieren der Linux-IP-Routing-Parameter - secret_interval und tcp_mem

30

Wir hatten heute ein kleines Failover-Problem mit einer unserer HAProxy-VMs. Als wir uns damit befassten, fanden wir Folgendes:

26. Januar 07:41:45 haproxy2-Kernel: [226818.070059] __ratelimit: 10 Rückrufe unterdrückt
26. Januar 07:41:45 haproxy2-Kernel: [226818.070064] Nicht genügend Socket-Speicher
26. Januar 07:41:47 haproxy2-Kernel: [226819.560048] Nicht genügend Socket-Speicher
26. Januar 07:41:49 haproxy2-Kernel: [226822.030044] Nicht genügend Socket-Speicher

Was laut diesem Link anscheinend mit geringen Standardeinstellungen für zu tun hat net.ipv4.tcp_mem. Deshalb haben wir sie gegenüber ihren Standardeinstellungen um das Vierfache erhöht (dies ist Ubuntu Server, nicht sicher, ob die Linux-Variante von Bedeutung ist):

Aktuelle Werte sind: 45984 61312 91968
Neue Werte sind: 183936 245248 367872

Danach wurde eine bizarre Fehlermeldung angezeigt:

26. Januar 08:18:49 haproxy1-Kernel: [2291.579726] Route-Hash-Kette zu lang!
26. Januar 08:18:49 haproxy1-Kernel: [2291.579732] Passen Sie Ihr secret_interval an!

Shh .. es ist ein Geheimnis !!

Dies hat offensichtlich damit zu tun, dass /proc/sys/net/ipv4/route/secret_intervalder Standardwert 600 ist und das periodische Leeren des Routen-Caches gesteuert wird

Das secret_intervalweist den Kernel an, wie oft ALLE Routen-Hash-Einträge weggeblasen werden sollen, unabhängig davon, wie neu / alt sie sind. In unserer Umwelt ist das im Allgemeinen schlecht. Die CPU wird jedes Mal, wenn der Cache geleert wird, Tausende von Einträgen pro Sekunde neu erstellen. Wir haben dies jedoch so eingestellt, dass es einmal am Tag ausgeführt wird, um Speicherlecks in Schach zu halten (obwohl wir noch nie einen hatten).

Obwohl wir dies gerne reduzieren, erscheint es seltsam, den gesamten Routen-Cache in regelmäßigen Abständen zu löschen , anstatt einfach alte Werte schneller aus dem Routen-Cache zu entfernen.

Nach einigen Nachforschungen haben wir herausgefunden, /proc/sys/net/ipv4/route/gc_elasticitywelche Option besser geeignet ist, um die Größe der Routentabelle zu kontrollieren:

gc_elasticitykann am besten als die durchschnittliche Bucket-Tiefe beschrieben werden, die der Kernel akzeptiert, bevor er beginnt, Routen-Hash-Einträge abzulaufen. Dies hilft, die Obergrenze der aktiven Routen beizubehalten.

Wir haben die Elastizität von 8 auf 4 angepasst, in der Hoffnung, dass sich der Routen-Cache selbst aggressiver beschneidet. Das secret_intervalfühlt sich für uns nicht richtig an. Aber es gibt eine Reihe von Einstellungen und es ist unklar, welche wirklich der richtige Weg sind, um hierher zu kommen.

  • / proc / sys / net / ipv4 / route / gc_elasticity (8)
  • / proc / sys / net / ipv4 / route / gc_interval (60)
  • / proc / sys / net / ipv4 / route / gc_min_interval (0)
  • / proc / sys / net / ipv4 / route / gc_timeout (300)
  • / proc / sys / net / ipv4 / route / secret_interval (600)
  • / proc / sys / net / ipv4 / route / gc_thresh (?)
  • rhash_entries (Kernelparameter, Standard unbekannt?)

Wir wollen das Linux-Routing nicht verschlechtern , deshalb haben wir Angst, mit einigen dieser Einstellungen zu experimentieren.

Kann jemand raten, welche Routing-Parameter für eine HAProxy-Instanz mit hohem Datenverkehr am besten zu optimieren sind?

Jeff Atwood
quelle

Antworten:

28

Ich bin noch nie auf dieses Problem gestoßen. Sie sollten jedoch wahrscheinlich die Breite Ihrer Hash-Tabelle erhöhen, um die Tiefe zu verringern. Mit "dmesg" sehen Sie, wie viele Einträge Sie aktuell haben:

$ dmesg | grep '^IP route'
IP route cache hash table entries: 32768 (order: 5, 131072 bytes)

Sie können diesen Wert mit dem Kernel-Boot-Befehlszeilenparameter ändern rhash_entries. Versuchen Sie es zuerst mit der Hand und fügen Sie es dann Ihrem lilo.confoder hinzu grub.conf.

Beispielsweise: kernel vmlinux rhash_entries=131072

Es ist möglich, dass Sie eine sehr begrenzte Hash-Tabelle haben, weil Sie Ihrer HAProxy-VM wenig Speicher zugewiesen haben (die Hash-Größe der Route wird abhängig vom gesamten RAM angepasst).

In Bezug auf tcp_mem, sei vorsichtig. Ihre anfänglichen Einstellungen lassen mich vermuten, dass Sie mit 1 GB RAM arbeiten, von denen 1/3 TCP-Sockets zugewiesen werden können. Jetzt haben Sie den TCP-Sockets 367872 * 4096 Byte = 1,5 GB RAM zugewiesen. Sie sollten sehr darauf achten, dass Ihnen nicht der Speicher ausgeht. Als Faustregel gilt, dass 1/3 des Speichers HAProxy und ein weiteres 1/3 dem TCP-Stack und das letzte 1/3 dem Rest des Systems zugewiesen wird.

Ich vermute, dass Ihre Meldung "Out of Socket Memory" von den Standardeinstellungen in tcp_rmemund stammt tcp_wmem. Standardmäßig sind jedem Socket 64 kB am Ausgang und 87 kB am Eingang zugewiesen. Dies bedeutet insgesamt 300 kB für eine Proxy-Verbindung, nur für Socket-Puffer. Wenn Sie diese 16 oder 32 kB für HAProxy hinzufügen, werden Sie feststellen, dass mit 1 GB RAM nur 3000 Verbindungen unterstützt werden.

Durch Ändern der Standardeinstellungen von tcp_rmemund tcp_wmem(mittlerer Parameter) können Sie den Arbeitsspeicher erheblich verringern. Ich erhalte gute Ergebnisse mit Werten von nur 4096 für den Schreibpuffer und 7300 oder 16060 in tcp_rmem(5 oder 11 TCP-Segmente). Sie können diese Einstellungen ohne Neustart ändern, sie gelten jedoch nur für neue Verbindungen.

Wenn Sie es vorziehen, Ihre sysctls nicht zu sehr zu berühren , können Sie mit dem neuesten HAProxy 1.4-dev8 diese Parameter in der globalen Konfiguration und pro Seite (Client oder Server) optimieren.

Ich hoffe das hilft!

Willy Tarreau
quelle
8

Das Out of socket memory errorist oft irreführend. In den meisten Fällen weist dies auf mit dem Internet verbundenen Servern nicht auf Probleme im Zusammenhang mit unzureichendem Arbeitsspeicher hin. Wie ich in einem Blog-Post ausführlicher erklärt habe , ist der häufigste Grund die Anzahl der Orphan Sockets. Ein verwaister Socket ist ein Socket, der keinem Dateideskriptor zugeordnet ist. Unter bestimmten Umständen gibt der Kernel das aus Out of socket memory error, obwohl Sie 2x oder 4x vom Limit entfernt sind ( /proc/sys/net/ipv4/tcp_max_orphans). Dies tritt häufig bei internetbasierten Diensten auf und ist völlig normal. In diesem Fall tcp_max_orphanssollten Sie mindestens die vierfache Anzahl von Waisen einstellen, die Sie normalerweise mit Ihrem Spitzenverkehrsaufkommen sehen.

Hören Sie nicht auf jede Beratung , die Abstimmung empfiehlt tcp_memoder tcp_rmemoder , tcp_wmemwenn Sie wirklich wissen , was du tust. Diejenigen, die diese Ratschläge geben, tun dies normalerweise nicht. Ihr Voodoo ist oft falsch oder ungeeignet für Ihre Umgebung und wird Ihr Problem nicht lösen. Es könnte es sogar noch schlimmer machen.

Tsuna
quelle
1
In diesem Fall ist die Meldung in dmesg anders. Sie sehen "zu viele verwaiste Sockets". Ich stimme Ihnen jedoch zu, dass Waisenkinder sehr viel Speicher verbrauchen können.
Willy Tarreau
Wenn Sie die Anzahl überschreiten, tritt /proc/sys/net/ipv4/tcp_max_orphansein anderer Fehler auf. Der gesamte Stack Exchange-Stack hat beispielsweise /proc/sys/net/ipv4/tcp_max_orphans65536 und /proc/net/sockstatführt zu TCP: inuse 2996 orphan 171 tw 15972 alloc 2998 mem 1621 - ein Unterschied, der nicht ignoriert werden kann.
Geoff Dalgas
-4

Wir stimmen einige dieser Parameter regelmäßig ab. Unser Standard für Handelsplattformen mit hohem Durchsatz und geringer Latenz ist:

net.ipv4.tcp_rmem = 4096 16777216 33554432
net.ipv4.tcp_wmem = 4096 16777216 33554432
net.ipv4.tcp_mem = 4096 16777216 33554432
net.core.rmem_default = 16777216
net.core.wmem_default = 16777216
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.netdev_max_backlog = 30000
net.core.netdev_max_backlog = 30000
Scott Alan Miller
quelle
1
pro Willys Mathematik bedeutet das, dass Ihr Standardspeicherdruck (mittlere Zahl) 68 GB beträgt ?! Mal drei (rmem, wmem, mem) ??
Jeff Atwood
10
Diese Tunables sind falsch und werden sehr häufig in Bankumgebungen verwendet, die dann blind kopiert werden. Sie haben kein Problem mit nur wenigen gleichzeitigen Sitzungen, aber selbst mit 100 TCP-Sockets werden Sie 3,2 GB RAM zuweisen. Solange die Latenz gering ist, werden Sie nichts Verdächtiges bemerken. Sie müssen während einer Übertragung lediglich einen Remotecomputer ausstecken, um zu sehen, wie die Ausgabepuffer gefüllt sind, oder eine lokale Aufgabe einfrieren und die Eingabepufferfüllung anzeigen. Das ist verrückt ...
Willy Tarreau
6
Jeff, das ist nicht mal drei. tcp_mem ist in pages und definiert die globale Größe. tcp_rmem und tcp_wmem sind in Bytes und definieren die Größe pro Socket.
Willy Tarreau
Diese Fehler sehen falsch aus, für gleichzeitige Server mit kleinen Daten möchten Sie nicht so viele Socket-Puffer reservieren, und tcp_mem unterscheidet sich grundlegend von r / wmem. Die Verwendung derselben Nummern ist nicht wirklich sinnvoll (eines ist Byte pro Verbindung, das andere Byte pro Verbindung) Seiten pro System)
eckes