Heim >Betrieb und Instandhaltung >Nginx >So optimieren Sie Nginx und Node.js für Netzwerke mit hoher Auslastung
Netzwerkoptimierung
Wenn Sie nicht zunächst die zugrunde liegenden Übertragungsmechanismen von Nginx und Node.js verstehen und eine gezielte Optimierung durchführen, ist die Optimierung der beiden, egal wie detailliert sie ist, umsonst. Normalerweise verbindet Nginx den Client und die Upstream-Anwendungen über einen TCP-Socket.
Unser System verfügt über viele Schwellenwerte und Einschränkungen für TCP, die über Kernel-Parameter festgelegt werden. Die Standardwerte dieser Parameter werden häufig für allgemeine Zwecke festgelegt und können den Anforderungen von Webservern an hohen Datenverkehr und kurze Lebensdauer nicht gerecht werden.
Hier sind einige Parameter, die als Kandidaten für die Optimierung von TCP verwendet werden können. Um sie wirksam zu machen, können Sie sie in die Datei /etc/sysctl.conf oder in eine neue Konfigurationsdatei wie /etc/sysctl.d/99-tuning.conf einfügen und dann sysctl -p ausführen Lassen Sie den Kernel sie laden. Wir verwenden sysctl-cookbook, um diese physische Arbeit zu erledigen.
Es ist zu beachten, dass die hier aufgeführten Werte sicher zu verwenden sind. Es wird jedoch dennoch empfohlen, die Bedeutung jedes Parameters zu studieren, um einen geeigneteren Wert basierend auf Ihrer Auslastung, Hardware und Nutzung auszuwählen.
Code kopieren Der Code lautet wie folgt:
net.ipv4.ip_local_port_range='1024 65000'
net.ipv4 .tcp_tw_reuse='1'
net.ipv4.tcp_fin_timeout='15'
net.core.netdev_max_backlog='4096'
net.core.rmem_max='16777216'
net.core.somaxconn='4096'
Net.core ='40 96 87380 span>
Heben Sie einige davon hervor. Eine wichtige.
net.ipv4.ip_local_port_range
Um den Downstream-Client für die Upstream-Anwendung zu bedienen, muss Nginx zwei TCP-Verbindungen öffnen, eine zum Client und eine zur Anwendung. Wenn ein Server viele Verbindungen empfängt, sind die verfügbaren Ports des Systems schnell erschöpft. Durch Ändern des Parameters net.ipv4.ip_local_port_range können Sie den Bereich der verfügbaren Ports vergrößern. Wenn in /var/log/syslog ein solcher Fehler gefunden wird: „Mögliches Syn-Flooding auf Port 80. Senden von Cookies“, bedeutet dies, dass das System keinen verfügbaren Port finden kann. Durch Erhöhen des Parameters net.ipv4.ip_local_port_range kann dieser Fehler reduziert werden.
net.ipv4.tcp_tw_reuse
Wenn der Server zwischen einer großen Anzahl von TCP-Verbindungen wechseln muss, wird eine große Anzahl von Verbindungen im Status „time_wait“ generiert. time_wait bedeutet, dass die Verbindung selbst geschlossen ist, die Ressourcen jedoch nicht freigegeben wurden. Wenn Sie net_ipv4_tcp_tw_reuse auf 1 setzen, kann der Kernel versuchen, Verbindungen wiederzuverwenden, wenn dies sicher ist. Dies ist viel kostengünstiger als die Wiederherstellung neuer Verbindungen.
Dies ist die Mindestzeit, die eine Verbindung im Status „time_wait“ warten muss, bevor sie wiederhergestellt wird. Eine Verkleinerung kann das Recycling beschleunigen. So überprüfen Sie den Verbindungsstatus
Verwenden Sie netstat:
netstat -tan | (Kernel 541)
tcp: 47461 (ESTAB 311, geschlossen 47135, OrphaNed 4, Synrecv 0, Timewait 47135/0), Ports 33938
Transport Total IP IPv6
* 541 - -
raw 0 0 Ut 13 10 3
tcp 326 325 1inet 339 335 4
frag 0 0 0
Wenn die Auslastung des Webservers allmählich zunimmt, werden wir auf einige seltsame Einschränkungen von Nginx stoßen. Die Verbindung wird unterbrochen und der Kernel meldet weiterhin Syn-Flood. Zu diesem Zeitpunkt sind der Lastdurchschnitt und die CPU-Auslastung sehr gering, und der Server kann offensichtlich mehr Verbindungen verarbeiten, was wirklich frustrierend ist.
Nach einer Untersuchung haben wir festgestellt, dass es im time_wait-Zustand viele Verbindungen gibt. Hier ist die Ausgabe von einem der Server:
Es gibt 47135 time_wait-Verbindungen! Darüber hinaus ist aus ss ersichtlich, dass es sich bei allen um geschlossene Verbindungen handelt. Dies weist darauf hin, dass der Server die meisten verfügbaren Ports verbraucht hat, und impliziert auch, dass der Server jeder Verbindung neue Ports zuweist. Das Optimieren des Netzwerks half ein wenig bei der Lösung des Problems, aber es waren immer noch nicht genügend Ports vorhanden.
Nach weiteren Recherchen habe ich ein Dokument über die Keepalive-Anweisung für Upstream-Verbindungen gefunden, in dem es heißt:
Legen Sie die maximale Anzahl inaktiver Keepalive-Verbindungen zum Upstream-Server fest. Diese Verbindungen werden im Cache des Arbeitsprozesses gespeichert.
Interessant. Theoretisch minimiert dieses Setup die Verschwendung von Verbindungen, indem Anfragen über zwischengespeicherte Verbindungen weitergeleitet werden. In der Dokumentation wird auch erwähnt, dass wir „proxy_http_version“ auf „1.1“ setzen und den „connection“-Header löschen sollten. Nach weiteren Recherchen habe ich festgestellt, dass dies eine gute Idee ist, da http/1.1 die Nutzung von TCP-Verbindungen im Vergleich zu http1.0 erheblich optimiert und Nginx standardmäßig http/1.0 verwendet.
Nach der Änderung wie im Dokument vorgeschlagen sieht unsere Uplink-Konfigurationsdatei folgendermaßen aus:
Kopieren Sie den Code. Der Code lautet wie folgt:
upstream backend_nodejs {
server nodejs-3:5016 max_fails=0 fail_timeout=10s;
server nodejs-4:5016 max_fails=0 fail_timeout=10s;
server nodejs-5:5016 max_fails=0 fail_timeout=10s;
server nodejs- 6:5016 max_fails=0 fail_timeout=10s;
keepalive 512;
}
Ich habe auch die Proxy-Einstellungen im Serverbereich wie vorgeschlagen geändert. Gleichzeitig wurde ein Proxy_next_upstream hinzugefügt, um ausgefallene Server zu überspringen, das Keepalive_Timeout des Clients angepasst und das Zugriffsprotokoll deaktiviert. Die Konfiguration sieht folgendermaßen aus:
Code kopieren Der Code lautet wie folgt:
server {
listen 80;
server_name fast.gosquared.com;
client_max_body_size 16m;
keepalive_timeout 10;
location / {
proxy_next_upstream error timeout http_500 http_50 2 http_503 http_504;
proxy_set_header Connection "";
proxy_http_version 1.1;
proxy_pass http://backend_nodejs;
}
access_log off;
error_log /dev/null crit;
}
Nachdem ich die neue Konfiguration übernommen habe, habe ich das festgestellt Die von den Servern belegten Sockets gingen um 90 % zurück. Anfragen können jetzt über deutlich weniger Verbindungen übermittelt werden. Die neue Ausgabe lautet wie folgt:
ss -s
total: 558 (kernel 604)
tcp: 4675 (estab 485, geschlossen 4183, verwaist 0, synrecv 0, timewait 4183/0), ports 2768
transport total ip ipv6
* 604 - -
raw 0 0 0
udp 13 10 3
tcp 492 491 1
inet 505 501 4
node.js
Dank des ereignisgesteuerten Designs, das E/A asynchron verarbeiten kann, kann node.js große Mengen verarbeiten Beträge out-of-the-box-Verbindungen und Anfragen. Obwohl es andere Optimierungsmethoden gibt, konzentriert sich dieser Artikel hauptsächlich auf den Prozessaspekt von node.js.
Knoten ist Single-Threaded und verwendet nicht automatisch mehrere Kerne. Mit anderen Worten: Die Anwendung kann nicht automatisch alle Funktionen des Servers nutzen.
Clustering von Knotenprozessen erreichen
Wir können die Anwendung so ändern, dass sie mehrere Threads aufteilt und Daten auf demselben Port empfängt, wodurch die Last über mehrere Kerne verteilt werden kann. Node verfügt über ein Cluster-Modul, das alle zum Erreichen dieses Ziels erforderlichen Tools bereitstellt. Das Hinzufügen dieser Tools zur Anwendung erfordert jedoch viel manuelle Arbeit. Wenn Sie Express verwenden, verfügt eBay über ein Modul namens Cluster2, das verwendet werden kann.
Kontextwechsel verhindern
Bei der Ausführung mehrerer Prozesse sollten Sie sicherstellen, dass jeder CPU-Kern gleichzeitig nur mit einem Prozess beschäftigt ist. Wenn die CPU n Kerne hat, sollten wir im Allgemeinen n-1 Anwendungsprozesse generieren. Dadurch wird sichergestellt, dass jeder Prozess eine angemessene Zeitspanne erhält, sodass ein Kern frei bleibt, damit der Kernel-Scheduler andere Aufgaben ausführen kann. Wir müssen außerdem sicherstellen, dass grundsätzlich keine anderen Aufgaben außer node.js auf dem Server ausgeführt werden, um CPU-Konflikte zu verhindern.
Wir haben einmal einen Fehler gemacht und zwei node.js-Anwendungen auf dem Server bereitgestellt, und dann hat jede Anwendung n-1 Prozesse geöffnet. Dadurch konkurrieren sie untereinander um die CPU, wodurch die Systemlast stark ansteigt. Obwohl unsere Server alle 8-Core-Maschinen sind, ist der durch den Kontextwechsel verursachte Leistungsaufwand immer noch deutlich zu spüren. Kontextwechsel bezieht sich auf das Phänomen, dass die CPU die aktuelle Aufgabe anhält, um andere Aufgaben auszuführen. Beim Umschalten muss der Kernel den gesamten Status des aktuellen Prozesses anhalten und dann einen anderen Prozess laden und ausführen. Um dieses Problem zu lösen, haben wir die Anzahl der von jeder Anwendung gestarteten Prozesse reduziert und sie die CPU gerecht teilen lassen. Dadurch ist die Systemlast gesunken:
Bitte beachten Sie das Bild oben, um zu sehen, wie das funktioniert Die Systemlast (blaue Linie) ist unter die Anzahl der CPU-Kerne (rote Linie) gesunken. Auf anderen Servern haben wir dasselbe gesehen. Da die Gesamtarbeitslast gleich bleibt, kann die Leistungsverbesserung in der obigen Grafik nur auf die Reduzierung der Kontextwechsel zurückgeführt werden.
Das obige ist der detaillierte Inhalt vonSo optimieren Sie Nginx und Node.js für Netzwerke mit hoher Auslastung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!