Hier sind 10 Leistungsregeln, die wir bei der Verwendung von Node.js befolgen:
1. Vermeiden Sie die Verwendung von synchronem Code
Vom Design her ist Node.js Single-Threaded. Damit ein einzelner Thread viele gleichzeitige Anforderungen verarbeiten kann, darf ein Thread niemals auf blockierende, synchrone oder lang laufende Vorgänge warten. Eine Besonderheit von Node.js besteht darin, dass es von oben nach unten entworfen und implementiert wird, um eine asynchrone Implementierung zu erreichen. Dies macht es ideal für den Einsatz mit ereignisbasierten Programmen.
Leider kann es weiterhin zu synchronen/blockierenden Aufrufen kommen. Beispielsweise gibt es für viele Dateisystemvorgänge sowohl synchrone als auch asynchrone Versionen, wie etwa writeFile und writeFileSync. Selbst wenn Sie Code zur Steuerung der Synchronisationsmethode verwenden, ist es immer noch möglich, versehentlich eine externe Funktionsbibliothek zu verwenden, die Aufrufe blockiert. Wenn Sie dies tun, sind die Auswirkungen auf die Leistung enorm.
// Good: write files asynchronously fs.writeFile('message.txt', 'Hello Node', function (err) { console.log("It's saved and the server remains responsive!"); }); // BAD: write files synchronously fs.writeFileSync('message.txt', 'Hello Node'); console.log("It's saved, but you just blocked ALL requests!");
Unsere Implementierung des Initialisierungsprotokolls enthielt versehentlich einen synchronen Aufruf zum Schreiben des Inhalts auf die Festplatte. Wenn wir keine Leistungstests durchführen, kann dieses Problem leicht ignoriert werden. Beim Test mit einer node.js-Instanz in der Entwicklerbox führt dieser synchrone Aufruf dazu, dass die Leistung von Tausenden von Anfragen pro Sekunde auf nur einige Dutzend sinkt.
2. Schalten Sie den Socket-Pool aus
Der HTTP-Client von Node.js verwendet automatisch den Socket-Pool: Standardmäßig ist jeder Host auf nur 5 Sockets beschränkt. Während die Wiederverwendung von Sockets den Ressourcenanstieg möglicherweise unter Kontrolle hält, kann sie zu einer Reihe von Engpässen führen, wenn Sie viele gleichzeitige Datenanforderungen vom selben Host bearbeiten müssen. In diesem Fall ist es eine gute Idee, den Wert von maxSockets zu erhöhen oder den Socket-Pool auszuschalten:
// Disable socket pooling var http = require('http'); var options = {.....}; options.agent = false; var req = http.request(options)
3 Lassen Sie nicht zu, dass statische Ressourcen Node.js verwenden
für CSS und Bilder Verwenden Sie für statische Ressourcen den Standard-WebServer anstelle von Node.js. Beispielsweise verwendet LinkedIn Mobile Nginx. Wir nutzen auch Content Delivery Networks (CDNs), die statische Assets auf Server auf der ganzen Welt kopieren können. Dies hat zwei Vorteile: (1) Es kann die Belastung unseres node.js-Servers reduzieren. (2) CDNs können die Wartezeit verkürzen, indem sie die Bereitstellung statischer Inhalte auf Servern ermöglichen, die näher an den Benutzern liegen.
4. Rendering auf dem Client
Vergleichen wir kurz die Unterschiede zwischen Server-Rendering und Client-Rendering. Wenn wir node.js zum Rendern auf der Serverseite verwenden, senden wir für jede Anfrage eine HTML-Seite wie die folgende zurück:
<!-- An example of a simple webpage rendered entirely server side --> <!DOCTYPE html> <html> <head> <title>LinkedIn Mobile</title> </head> <body> <div class="header"> <img src="http://mobile-cdn.linkedin.com/images/linkedin.png" alt="LinkedIn"/> </div> <div class="body"> Hello John! </div> </body> </html>
Bitte achten Sie auf alle Inhalte dieser Seite, mit Ausnahme der Der Name des Benutzers ist statischer Inhalt: Der Inhalt ist für jeden Benutzer und jedes erneute Laden der Seite derselbe. Daher ist es effizienter, Node.js nur den von der Seite benötigten dynamischen Inhalt in JSON-Form zurückgeben zu lassen.
{"name": "John"}
Der Rest der Seite – alles statisches HTML-Markup – kann in einer JavaScript-Vorlage (z. B. der Vorlage underscore.js) platziert werden:
<!-- An example of a JavaScript template that can be rendered client side --> <!DOCTYPE html> <html> <head> <title>LinkedIn Mobile</title> </head> <body> <div class="header"> <img src="http://mobile-cdn.linkedin.com/images/linkedin.png" alt="LinkedIn"/> </div> <div class="body"> Hello <%= name %>! </div> </body> </html>
Die Leistungsverbesserung kommt von diesen Stellen: Wie im dritten Punkt erwähnt, können statische JavaScript-Vorlagen serverseitig über den Webserver (z. B. Nginx) bereitgestellt oder über ein besseres CDN implementiert werden. Darüber hinaus können JavaScript-Vorlagen im Browser zwischengespeichert oder lokal gespeichert werden. Nach dem ersten Laden der Seite müssen nur JSON-Daten an den Client gesendet werden, was am effektivsten ist. Diese Methode kann die CPU-, IO- und Node.js-Last erheblich reduzieren.
5. Verwenden Sie gzip
Viele Server und Clients unterstützen gzip, um Anfragen und Antworten zu komprimieren. Egal, ob Sie Clients beantworten oder Anfragen an Remote-Server senden, nutzen Sie das volle Potenzial aus.
6. Parallelisierung
Versuchen Sie, alle Ihre Blockierungsvorgänge zu parallelisieren – Senden von Anfragen an Remote-Dienste, DB-Aufrufe, Dateisystemzugriffe. Dadurch wird die Wartezeit des langsamsten Blockierungsvorgangs verkürzt und nicht die Wartezeit aller Blockierungsvorgänge. Um Rückrufe und Fehlerbehandlung sauber zu halten, verwenden wir Step, um den Ablauf zu steuern.
7. Sitzungsliberalisierung
LinkedIn Mobile verwendet das Express-Framework, um den Anfrage-/Antwortzyklus zu verwalten. Viele Express-Beispiele umfassen die folgende Konfiguration:
app.use(express.session({ Secret: "keyboard cat" }));
Standardmäßig werden Sitzungsdaten im Speicher gespeichert. Dies führt zu einem enormen Mehraufwand zum Server, insbesondere wenn die Anzahl der Benutzer wächst. Sie können einen externen Sitzungsspeicher wie MongoDB oder Redis verwenden, aber jede Anfrage verursacht den Overhead eines Remote-Aufrufs zum Abrufen der Sitzungsdaten. Wenn möglich, ist es am besten, alle zustandslosen Daten auf der Serverseite zu speichern. Wenn Sie die Sitzung freigeben, indem Sie die oben genannte Express-Konfiguration nicht einbeziehen, erzielen Sie eine bessere Leistung.
8. Verwenden Sie Binärmodule
Ersetzen Sie nach Möglichkeit JavaScript-Module durch Binärmodule. Wenn wir beispielsweise vom in JavaScript geschriebenen SHA-Modul zur kompilierten Version von Node.js wechseln, werden wir einen großen Leistungssprung sehen:
// Use built in or binary modules var crypto = require('crypto'); var hash = crypto.createHmac("sha1",key).update(signatureBase).digest("base64");
9. Ersetzen Sie die Client-Bibliothek durch Standard-V8-JavaScript
Viele JavaScript-Bibliotheken werden für die Verwendung in Webbrowsern erstellt, weil sich die JavaScript-Umgebung unterscheidet: Einige Browser unterstützen beispielsweise Funktionen wie forEach, Map und Reduce, andere jedoch nicht. Daher verwenden Clientbibliotheken oft viel ineffizienten Code, um Browserunterschiede zu überwinden. In Node.js hingegen wissen Sie genau, welche JavaScript-Methoden gültig sind: Die V8-JavaScript-Engine unterstützt die ECMAScript-Implementierung von Node.js, wie in ECMA-262 5th Edition angegeben. Ersetzen Sie einfach die Client-Bibliothek durch standardmäßige V8-JavaScript-Funktionen und Sie werden erhebliche Leistungsverbesserungen feststellen.
10. Halten Sie Ihren Code klein und leicht
Die Verwendung mobiler Geräte macht den Zugriff langsam und die Latenz hoch, was uns dazu anhält, unseren Code klein und leicht zu halten. Behalten Sie die gleiche Philosophie auch für den Servercode bei. Schauen Sie gelegentlich auf Ihre Entscheidungen zurück und stellen Sie sich Fragen wie: „Brauchen wir dieses Modul wirklich?“, „Warum verwenden wir dieses Framework und lohnt sich der Mehraufwand?“, „Können wir es auf einfachere Weise umsetzen?“ ?" Kleinerer und leichterer Code ist normalerweise effizienter und schneller.
Probieren Sie es aus
Wir arbeiten hart daran, unsere mobilen Apps schnell zu machen. Probieren Sie es mit der iPhone-App, der Android-App und der mobilen HTML5-Version aus und teilen Sie uns mit, wie es Ihnen geht.
Weitere Artikel zu den 10 Tipps zur Leistungsoptimierung für NodeJS finden Sie auf der chinesischen PHP-Website!