Diese Übersetzung zur Verfügung gestellt von StrongLoop / IBM.

Dieses Dokument kann im Vergleich zur englischen Dokumentation veraltet sein. Aktuelle Updates finden Sie in der englischen Dokumentation.

Best Practices in Produktionsumgebungen: Leistung und Zuverlässigkeit

Überblick

In diesem Beitrag werden Best Practices in Bezug auf Leistung und Zuverlässigkeit für Express-Anwendungen behandelt, die in der Produktionsumgebung bereitgestellt werden.

Dieses Thema gehört sicherlich zur “DevOps”-Welt und deckt traditionelle Entwicklungs- und Betriebsprozesse ab. Entsprechend sind die Informationen hier in zwei Teile unterteilt:

Empfehlungen für Maßnahmen an Ihrem Code

Dies sind einige Beispiele für Maßnahmen, die Sie an Ihrem Code vornehmen können, um die Anwendungsleistung zu verbessern:

GZIP-Komprimierung verwenden

Mit der GZIP-Komprimierung lässt sich die Größe des Antworthauptteils deutlich verringern und somit die Geschwindigkeit der Webanwendung erhöhen. Verwenden Sie die Middleware compression für die GZIP-Komprimierung in Ihrer Express-Anwendung. Beispiel:

const compression = require('compression')
const express = require('express')
const app = express()
app.use(compression())

Bei Websites mit hohem Datenverkehr in Produktionsumgebungen lässt sich die Komprimierung am besten installieren, indem sie auf Reverse Proxy-Ebene implementiert wird (siehe Reverse Proxy verwenden). In diesem Fall wird die Middleware “compression” nicht benötigt. Details zur Aktivierung der GZIP-Komprimierung in Nginx siehe Modul ngx_http_gzip_module in der Nginx-Dokumentation.

Keine synchronen Funktionen verwenden

Synchrone Funktionen und Methoden belasten den Ausführungsprozess, bis sie zurückgegeben werden. Ein einzelner Aufruf für eine synchrone Funktion kann in wenigen Mikrosekunden oder Millisekunden zurückgegeben werden. Bei Websites mit hohem Datenverkehr hingegen summieren sich diese Aufrufe und verringern die Leistung der Anwendung. Sie sollten also deren Verwendung in Produktionsumgebungen vermeiden.

Auch wenn Node und viele andere Module synchrone und asynchrone Versionen ihrer Funktionen bieten, sollten Sie in Produktionsumgebungen immer die asynchrone Version verwenden. Nur beim ersten Systemstart ist die Verwendung einer synchronen Funktion begründet.

Wenn Sie Node.js 4.0 und höher oder io.js 2.1.0 und höher verwenden, können Sie über das Befehlszeilenflag --trace-sync-io eine Warnung und einen Stack-Trace ausgeben, wenn Ihre Anwendung eine synchrone API verwendet. Auch wenn Sie diese natürlich nicht in der Produktionsumgebung verwenden werden, soll dadurch trotzdem sichergestellt werden, dass Ihr Code in der Produktionsumgebung eingesetzt werden kann. Weitere Informationen hierzu siehe Wöchentliches Update für io.js 2.1.0.

Für statische Dateien Middleware verwenden

Bei der Entwicklung können Sie res.sendFile() für statische Dateien verwenden. Dies gilt jedoch nicht für die Produktionsumgebung, da diese Funktion bei jeder Dateianforderung aus dem Dateisystem lesen muss. Dadurch kommt es zu deutlichen Latenzen, die sich negativ auf die Gesamtleistung der Anwendung auswirken. Beachten Sie, dass res.sendFile() nicht mit dem Systemaufruf sendfile implementiert wird, wodurch dieser deutlich effizienter wäre.

Verwenden Sie stattdessen die Middleware serve-static (oder etwas Vergleichbares), die für die Bereitstellung von Dateien für Express-Anwendungen optimiert ist.

Die bessere Option wäre, für statische Dateien einen Reverse Proxy zu verwenden. Weitere Informationen siehe Reverse Proxy verwenden.

Auf ordnungsgemäße Protokollierung achten

Im Allgemeinen gibt es für die Protokollierung Ihrer Anwendung zwei Gründe: 1) Debugging und 2) Protokollierung von Anwendungsaktivitäten (im Wesentlichen alles andere, außer Debugging). Die Verwendung vonconsole.log() oder console.err() zur Ausgabe von Protokollnachrichten an das Terminal ist in der Entwicklung gängige Praxis. Diese Funktionen sind jedoch synchron, wenn das Ziel ein Terminal oder eine Datei ist. Sie sind also für Produktionsumgebungen nicht geeignet, es sei denn, Sie leiten die Ausgabe per Pipe zu einem anderen Programm um.

Für Debuggingzwecke

Wenn Sie die Protokollierung für Debuggingzwecke nutzen, sollten Sie statt console.log() besser ein spezielles Debuggingmodul wie debug verwenden. Mit einem solchen Modul können Sie über die Umgebungsvariable DEBUG steuern, welche Debugnachrichten an console.err() gesendet werden (falls vorhanden). Um Ihre Anwendung rein asynchron zu halten, können Sie trotzdem console.err() per Pipe zu einem anderen Programm umleiten. Sie nehmen dann aber kein Debugging in der Produktionsumgebung vor, richtig?

Für Anwendungsaktivitäten

Wenn Sie Anwendungsaktivitäten protokollieren (z. B. den Datenverkehr oder API-Aufrufe aufzeichnen), sollten Sie statt console.log() eine Protokollierungsbibliothek wie Winston oder Bunyan verwenden. Einen ausführlichen Vergleich dieser beiden Bibliotheken finden Sie im StrongLoop-Blogbeitrag Vergleich von Winston und Bunyan für die Node.js-Protokollierung.

Ausnahmebedingungen ordnungsgemäß handhaben

Node-Anwendungen stürzen ab, wenn eine nicht abgefangene Ausnahmebedingung vorkommt. Wenn diese Ausnahmebedingungen nicht behandelt und entsprechende Maßnahmen eingeleitet werden, stürzt Ihre Express-Anwendung ab und geht offline. Wenn Sie dem nachfolgenden Rat in Sicherstellen, dass Ihre Anwendung automatisch neu gestartet wird folgen, wird Ihre Anwendung nach einem Absturz wiederhergestellt. Glücklicherweise haben Express-Anwendungen nur eine kurze Initialisierungszeit. Nichtsdestotrotz sollten Sie in erster Linie solche Abstürze vermeiden. Und hierzu müssen Sie Ausnahmebedingungen ordnungsgemäß handhaben.

Mit folgenden Verfahren stellen Sie sicher, dass alle Ausnahmebedingungen gehandhabt werden:

Um näher auf diese Themen eingehen zu können, müssen Sie sich ein grundlegendes Verständnis der Fehlerbehandlung in Node und Express aneignen: Verwendung von Error-first-Callbacks und Propagieren von Fehlern in Middleware. Node verwendet die Konvention “Error-first-Callback” für die Rückgabe von Fehlern von asynchronen Funktionen, bei denen der erste Parameter zur Callback-Funktion das Fehlerobjekt ist, gefolgt von Ergebnisdaten in den nachfolgenden Parametern. Um anzugeben, dass kein Fehler vorliegt, müssen Sie “null” als ersten Parameter übergeben. Die Callback-Funktion muss der Konvention “Error-first-Callback” folgen, um den Fehler sinnvoll bearbeiten zu können. In Express hat sich bewährt, die Funktion “next()” zu verwenden, um Fehler über die Middleware-Chain zu propagieren.

Weitere Informationen zu den Grundlagen der Fehlerbehandlung siehe:

Was Sie unterlassen sollten

Sie sollten auf keinen Fall per Listener das Ereignis uncaughtException überwachen, das ausgegeben wird, wenn eine Ausnahmebedingung bis zurück zur Ereignisschleife bestehen bleibt. Durch das Hinzufügen eines Ereignislisteners für uncaughtException verändert sich das Standardverhalten des Prozesses, über das eine Ausnahmebedingung festgestellt wird. Der Prozess läuft dann trotz der Ausnahmebedingung weiter. Dies mag sich vielleicht gut anhören, um einem Absturz Ihrer Anwendung vorzubeugen. Das Ausführen einer Anwendung nach einer nicht abgefangenen Ausnahmebedingung ist aber eine durchaus riskante Vorgehensweise und wird nicht empfohlen, da der Prozessstatus störanfällig und unvorhersehbar wird.

Außerdem wird die Verwendung von uncaughtException offiziell als grobes Vorgehen angesehen, sodass es den Vorschlag gibt, die Funktion aus dem Kern zu entfernen. Das Überwachen von uncaughtException per Listener ist also keine gute Idee. Daher empfehlen wir Dinge wie Mehrfachprozesse und Supervisoren: Ein Absturz und anschließender Neustart ist häufig die zuverlässigste Art der Fehlerbehebung.

Zudem empfehlen wir, domains nicht zu verwenden. Mit diesem Modul, das zudem veraltet ist, lässt sich das Problem in der Regel nicht lösen.

“try-catch” verwenden

“try-catch” ist ein JavaScript-Sprachkonstrukt, mit dem Sie Ausnahmebedingungen in synchronem Code abfangen können. Verwenden Sie “try-catch” beispielsweise, um JSON-Parsing-Fehler wie unten gezeigt zu bearbeiten.

Verwenden Sie ein Tool wie JSHint oder JSLint, um implizite Ausnahmebedingungen wie Referenzfehler bei nicht definierten Variablen zu finden.

Dies ist ein Beispiel zur Verwendung von “try-catch”, um eine potenzielle “process-crashing”-Ausnahmebedingung zu handhaben. Diese Middlewarefunktion akzeptiert einen Abfragefeldparameter mit dem Namen “params”, der ein JSON-Objekt ist.

app.get('/search', (req, res) => {
  // Simulating async operation
  setImmediate(() => {
    const jsonStr = req.query.params
    try {
      const jsonObj = JSON.parse(jsonStr)
      res.send('Success')
    } catch (e) {
      res.status(400).send('Invalid JSON string')
    }
  })
})

“try-catch” funktioniert jedoch nur in synchronem Code. Da die Node-Plattform primär asynchron ist (insbesondere in einer Produktionsumgebung), lassen sich mit “try-catch” nicht besonders viele Ausnahmebedingungen abfangen.

“Promises” verwenden

Mit “Promises” werden alle Ausnahmebedingungen (explizite und implizite) in asynchronen Codeblöcken gehandhabt, die then() verwenden. Sie müssen nur .catch(next) am Ende der Promises-Ketten hinzufügen. Beispiel:

app.get('/', (req, res, next) => {
  // do some sync stuff
  queryDb()
    .then((data) => makeCsv(data)) // handle data
    .then((csv) => { /* handle csv */ })
    .catch(next)
})

app.use((err, req, res, next) => {
  // handle error
})

Jetzt werden alle asynchronen und synchronen Fehler zur Middleware “error” propagiert.

Es gibt jedoch zwei Vorbehalte:

  1. Der gesamte asynchrone Code muss “Promises” zurückgeben (außer Emitter). Wenn eine bestimmte Bibliothek keine “Promises” zurückgibt, müssen Sie das Basisobjekt mit einer Helper-Funktion wie Bluebird.promisifyAll() konvertieren.
  2. Ereignisemitter (wie Streams) können nach wie vor nicht abgefangene Ausnahmebedingungen verursachen. Sie müssen also sicherstellen, dass Sie das Fehlerereignis ordnungsgemäß handhaben. Beispiel:
const wrap = fn => (...args) => fn(...args).catch(args[2])

app.get('/', wrap(async (req, res, next) => {
  const company = await getCompanyById(req.query.id)
  const stream = getLogoStreamById(company.id)
  stream.on('error', next).pipe(res)
}))

Weitere Informationen zur Fehlerbehandlung mithilfe von “Promises” siehe:

Empfehlungen für Maßnahmen an Ihrer Umgebung/Ihrem Setup

Dies sind einige Beispiele für Maßnahmen, die Sie an Ihrer Systemumgebung vornehmen können, um die Anwendungsleistung zu verbessern:

NODE_ENV auf “production” festlegen

In der Umgebungsvariablen NODE_ENV wird die Umgebung angegeben, in der eine Anwendung ausgeführt wird (in der Regel ist dies die Entwicklungs- oder Produktionsumgebung). Am einfachsten lässt sich die Leistung verbessern, indem NODE_ENV auf “production” festgelegt wird.

Durch das Festlegen von NODE_ENV auf “production” führt Express Folgendes aus:

Tests deuten darauf hin, dass alleine dadurch die Anwendungsleistung um den Faktor 3 verbessert werden kann!

Wenn Sie umgebungsspezifischen Code schreiben müssen, können Sie den Wert von NODE_ENV mit process.env.NODE_ENV überprüfen. Beachten Sie, dass die Überprüfung des Werts seiner Umgebungsvariablen eine leistungsbezogene Penalisierung nach sich zieht. Sie sollten also sehr sparsam damit umgehen.

In einer Entwicklungsumgebung wird die Umgebungsvariable in der Regel in Ihrer interaktiven Shell festgelegt, indem Sie beispielsweise export oder Ihre Datei .bash_profile verwenden. Im Allgemeinen sollten Sie dies nicht auf dem Produktionsserver vornehmen. Verwenden Sie stattdessen das Init-System (systemd oder Upstart) Ihres Betriebssystems. Der nächste Abschnitt enthält weitere Details zur Verwendung des Init-Systems im Allgemeinen. Die Festlegung von NODE_ENV ist jedoch für das Leistungsverhalten so wichtig (und so einfach durchzuführen), dass hier besonders darauf eingegangen wird.

Verwenden Sie bei Upstart das Schlüsselwort env in Ihrer Jobdatei. Beispiel:


# /etc/init/env.conf
 env NODE_ENV=production

Weitere Informationen hierzu siehe Upstart Intro, Cookbook and Best Practices.

Verwenden Sie bei systemd die Anweisung Environment in Ihrer Einheitendatei. Beispiel:


# /etc/systemd/system/myservice.service
Environment=NODE_ENV=production

Weitere Informationen siehe Umgebungsvariablen in systemd-Einheiten verwenden.

Wenn Sie StrongLoop Process Manager verwenden, können Sie auch die Umgebungsvariable festlegen, wenn Sie StrongLoop Process Manager als Service installieren.

Automatischen Neustart Ihrer Anwendung sicherstellen

In der Produktionsumgebung sollte die Anwendung nie offline sein. Das bedeutet, dass Sie sicherstellen müssen, dass die Anwendung bei einem Absturz der Anwendung oder des Servers immer wieder neu gestartet wird. Auch wenn man hofft, das keines dieser Ereignisse jemals eintritt, muss man doch mit beiden Möglichkeiten rechnen und:

Node-Anwendungen stürzen ab, wenn eine nicht abgefangene Ausnahmebedingung auftritt. Als Erstes müssen Sie in einem solchen Fall sicherstellen, dass Ihre Anwendung ausreichend getestet wurde und in der Lage ist, alle Ausnahmebedingungen zu handhaben (weitere Informationen siehe Ausnahmebedingungen ordnungsgemäß handhaben). Die sicherste Maßnahme ist jedoch, einen Mechanismus zu implementieren, über den bei einem Absturz der Anwendung ein automatischer Neustart der Anwendung ausgeführt wird.

Prozessmanager verwenden

In Entwicklungumgebungen wird die Anwendung einfach über die Befehlszeile mit node server.js oder einer vergleichbaren Datei gestartet. In der Produktionsumgebung hingegen ist durch diese Vorgehensweise die Katastrophe bereits vorprogrammiert. Wenn die Anwendung abstürzt, ist sie solange offline, bis Sie sie erneut starten. Um sicherzustellen, dass Ihre Anwendung nach einem Absturz neu gestartet wird, sollten Sie einen Prozessmanager verwenden. Ein Prozessmanager ist ein “Container” für Anwendungen, der die Bereitstellung erleichtert, eine hohe Verfügbarkeit sicherstellt und die Verwaltung der Anwendung zur Laufzeit ermöglicht.

Neben einem Neustart der Anwendung nach einem Absturz bietet ein Prozessmanager noch weitere Möglichkeiten:

Die gängigsten Prozessmanager für Node sind:

Einen Vergleich der Features und Funktionen dieser Prozessmanager finden Sie hier: http://strong-pm.io/compare/. Eine ausführliche Einführung in diese drei Prozessmanager finden Sie hier: Prozessmanager für Express-Anwendungen.

Die Verwendung eines dieser Prozessmanager reicht aus, um Ihre Anwendung betriebsbereit zu halten, selbst wenn sie hin und wieder abstürzt.

StrongLoop PM verfügt jedoch über zahlreiche Features und Funktionen, die sich speziell auf Implementierungen in der Produktionsumgebung beziehen. Sie können diesen Prozessmanager und die zugehörigen StrongLoop-Tools für folgende Zwecke verwenden:

Wie unten beschrieben, erfolgt ein automatischer Neustart beim Systemwiederanlauf, wenn Sie StrongLoop Process Manager über Ihr Init-System als Betriebssystemservice installieren. Dadurch bleiben Ihre Anwendungsprozesse und Cluster dauerhaft betriebsbereit.

Init-System verwenden

Als nächste Ebene der Zuverlässigkeit müssen Sie sicherstellen, dass Ihre Anwendung bei einem Serverneustart neu gestartet wird. Systeme können immer wieder aus verschiedenen Gründen abstürzen. Um sicherzustellen, dass Ihre Anwendung bei einem Serverabsturz neu gestartet wird, können Sie das in Ihr Betriebssystem integrierte Init-System verwenden. Die beiden wichtigsten Init-Systeme sind aktuell systemd und Upstart.

Es gibt zwei Möglichkeiten, Init-Systeme mit Ihrer Express-Anwendung zu verwenden:

systemd

“systemd” ist ein Linux-System und Service-Manager. Die meisten wichtigen Linux-Distributionen haben “systemd” als Init-Standardsystem übernommen.

Eine “systemd”-Servicekonfigurationsdatei wird als Einheitendatei bezeichnet, die die Endung “.service” hat. Dies ist ein Beispiel für eine Einheitendatei zur direkten Verwaltung einer Node-Anwendung (ersetzen Sie den Text in Fettdruck durch Werte für Ihr System und Ihre Anwendung):


[Unit]
Description=Awesome Express App

[Service]
Type=simple
ExecStart=/usr/local/bin/node /projects/myapp/index.js
WorkingDirectory=/projects/myapp

User=nobody
Group=nogroup

# Environment variables:
Environment=NODE_ENV=production

# Allow many incoming connections
LimitNOFILE=infinity

# Allow core dumps for debugging
LimitCORE=infinity

StandardInput=null
StandardOutput=syslog
StandardError=syslog
Restart=always

[Install]
WantedBy=multi-user.target

Weitere Informationen zu “systemd” siehe systemd-Referenz (Man-Page).

StrongLoop Process Manager als “systemd”-Service

Sie können StrongLoop Process Manager problemlos als “systemd”-Service installieren. Dadurch wird beim Serverneustart StrongLoop Process Manager automatisch neu gestartet. Dadurch wiederum werden alle Anwendungen neu gestartet, die von diesem Prozessmanager verwaltet werden.

So installieren Sie StrongLoop Process Manager als “systemd”-Service:

$ sudo sl-pm-install --systemd

Starten Sie dann den Service mit:

$ sudo /usr/bin/systemctl start strong-pm

Weitere Informationen hierzu finden Sie im Thema Produktionshost einrichten (in der StrongLoop-Dokumentation).

Upstart

“Upstart” ist ein Systemtool, das auf vielen Linux-Distributionen verfügbar ist. Mit diesem Tool können Aufgaben (Tasks) und Services beim Systemstart gestartet, beim Herunterfahren gestoppt und auch überwacht werden. Sie können Ihre Express-Anwendung oder einen Prozessmanager als Service konfigurieren. “Upstart” startet diese dann bei einem Absturz automatisch neu.

Ein “Upstart”-Service wird als Jobkonfigurationsdatei (auch als “Job” bezeichnet) definiert, deren Dateiname mit .conf endet. Das folgende Beispiel zeigt, wie ein Job namens “myapp” für eine Anwendung namens “myapp” erstellt wird, wobei sich die Hauptdatei im Verzeichnis /projects/myapp/index.js befindet.

Erstellen Sie eine Datei namens myapp.conf unter /etc/init/ mit dem folgenden Inhalt (ersetzen Sie den Text in Fettdruck durch Werte für Ihr System und Ihre Anwendung):


# When to start the process
start on runlevel [2345]

# When to stop the process
stop on runlevel [016]

# Increase file descriptor limit to be able to handle more requests
limit nofile 50000 50000

# Use production mode
env NODE_ENV=production

# Run as www-data
setuid www-data
setgid www-data

# Run from inside the app dir
chdir /projects/myapp

# The process to start
exec /usr/local/bin/node /projects/myapp/index.js

# Restart the process if it is down
respawn

# Limit restart attempt to 10 times within 10 seconds
respawn limit 10 10

Hinweis: Dieses Script erfordert Upstart 1.4 oder höher mit Unterstützung auf Ubuntu 12.04-14.10.

Da der Job so konfiguriert ist, dass er beim Systemstart ausgeführt wird, wird Ihre Anwendung zusammen mit dem Betriebssystem gestartet und automatisch neu gestartet, wenn die Anwendung abstürzt oder das System heruntergefahren wird.

Neben dem automatischen Neustart der Anwendung können Sie mit Upstart die folgenden Befehle verwenden:

Weitere Informationen zu “Upstart” siehe Upstart Intro, Cookbook and Best Practises.

StrongLoop Process Manager als “Upstart”-Service

Sie können StrongLoop Process Manager problemlos als “Upstart”-Service installieren. Dadurch wird beim Serverneustart StrongLoop Process Manager automatisch neu gestartet. Dadurch wiederum werden alle Anwendungen neu gestartet, die von diesem Prozessmanager verwaltet werden.

So installieren Sie StrongLoop Process Manager als “Upstart 1.4”-Service:

$ sudo sl-pm-install

Fühen Sie dann den Service aus mit:

$ sudo /sbin/initctl start strong-pm

Hinweis: Auf Systemen, die Upstart 1.4 nicht unterstützen, sind die Befehle leicht unterschiedlich. Weitere Informationen hierzu siehe das Thema Einrichtung eines Produktionshosts (in der StrongLoop-Dokumentation).

Anwendung in einem Cluster ausführen

In einem Multi-Core-System können Sie die Leistung einer Node-Anwendung mehrmals erhöhen, indem Sie einen Cluster von Prozessen starten. Ein Cluster führt mehrere Instanzen der Anwendung aus, idealerweise eine Instanz auf jedem CPU-Core. Dadurch werden die Arbeitslasten und die Tasks auf die Instanzen verteilt.

Wichtig. Da die Anwendungsinstanzen als separate Prozesse ausgeführt werden, nutzen sie nicht dieselbe Hauptspeicherkapazität gemeinsam. Das heißt, Objekte befinden sich für jede Instanz der Anwendung auf lokaler Ebene. Daher kann der Status im Anwendungscode nicht beibehalten werden. Sie können jedoch einen speicherinternen Datenspeicher wie Redis verwenden, um sitzungsrelevante Daten und Statusinformationen zu speichern. Diese Einschränkung trifft im Wesentlichen auf alle Formen der horizontalen Skalierung zu, unabhängig davon, ob es sich um Clustering mit mehreren Prozessen oder mehreren physischen Servern handelt.

Bei in Gruppen zusammengefassten Anwendungen (geclusterte Anwendungen) können Verarbeitungsprozesse einzeln ausfallen, ohne dass sich dies auf die restlichen Prozesse auswirkt. Neben den Leistungsvorteilen ist die Fehlerisolierung ein weiterer Grund, einen Cluster von Anwendungsprozessen auszuführen. Wenn ein Verarbeitungsprozess abstürzt, müssen Sie sicherstellen, dass das Ereignis protokolliert und ein neuer Prozess mithilfe von “cluster.fork()” gestartet wird.

Clustermodule von Node verwenden

Das Clustering erfolgt über das Clustermodul von Node. Dadurch wird ein Masterprozess eingeleitet, um Verarbeitungsprozesse zu starten und eingehende Verbindungen auf die Verarbeitungsprozesse zu verteilen. Anstatt dieses Modul jedoch direkt zu verwenden, ist es deutlich besser, eines der vielen angebotenen Tools einzusetzen, das diesen Vorgang automatisch für Sie ausführt, wie beispielsweise node-pm oder cluster-service.

StrongLoop Process Manager verwenden

Wenn Sie Ihre Anwendung auf StrongLoop Process Manager (PM) bereitstellen, können Sie die Vorteile des Clustering nutzen, ohne Ihren Anwendungscode ändern zu müssen.

Wenn StrongLoop Process Manager (PM) eine Anwendung ausführt, wird diese automatisch in einem Cluster ausgeführt. Die Anzahl der Verarbeitungsprozesse entspricht dabei der Anzahl der CPU-Cores im System. Sie können die Anzahl der Verarbeitungsprozesse manuell im Cluster ändern. Hierfür verwenden Sie das Befehlszeilentool “slc”, ohne die Anwendung stoppen zu müssen.

Beispiel: Angenommen, Sie haben Ihre Anwendung auf prod.foo.com bereitgestellt, und StrongLoop PM ist auf Port 8701 (Standardport) empfangsbereit. Dann müssen Sie die Clustergröße mithilfe von “slc” auf “8” einstellen.

$ slc ctl -C http://prod.foo.com:8701 set-size my-app 8

Weitere Informationen zum Clustering mit StrongLoop PM finden Sie im Thema Clustering in der StrongLoop-Dokumentation.

Anforderungsergebnisse im Cache speichern

Eine weitere Strategie zur Verbesserung des Leistungsverhaltens in Produktionsumgebungen ist das Speichern von Anforderungergebnissen im Cache. Ihre Anwendung muss also diese Operation nicht wiederholt ausführen, um dieselbe Anforderung wiederholt zu bedienen.

Mithilfe eines Caching-Servers wie Varnish oder Nginx (siehe auch Nginx Caching) lassen sich Geschwindigkeit und Leistung Ihrer Anwendung hervorragend verbessern.

Load Balancer verwenden

Unabhängig davon, wie gut eine Anwendung optimiert wurde, kann eine Einzelinstanz nur eine begrenzte Arbeitslast oder einen begrenzten Datenverkehr handhaben. Eine Möglichkeit, eine Anwendung zu skalieren, ist die Ausführung mehrerer Instanzen dieser Anwendung und die Verteilung des Datenverkehrs über eine Lastausgleichsfunktion (Load Balancer) vorzunehmen. Die Einrichtung eines solchen Load Balancer kann helfen, Leistung und Geschwindigkeit Ihrer Anwendung zu verbessern. Zudem lässt sich dadurch die Anwendung besser skalieren als mit einer Einzelinstanz.

Ein Load Balancer ist in der Regel ein Reverse Proxy, der den Datenverkehr zu und von mehreren Anwendungsinstanzen und Servern koordiniert. Sie können ohne großen Aufwand einen Load Balancer für Ihre Anwendung einrichten. Verwenden Sie hierzu Nginx oder HAProxy.

Bei einer solchen Lastverteilung müssen Sie sicherstellen, dass Anforderungen, die einer bestimmten Sitzungs-ID zugeordnet sind, mit dem Prozess verbunden sind, von dem sie ursprünglich stammen. Dies wird auch als Sitzungsaffinität oder Affine Sitzungen bezeichnet und kann durch den obigen Vorschlag, einen Datenspeicher wie Redis für Sitzungsdaten zu verwenden (je nach Anwendung), umgesetzt werden. Eine Beschreibung hierzu siehe Mehrere Knoten verwenden.

StrongLoop Process Manager mit einem Nginx Load Balancer verwenden

StrongLoop Process Manager lässt sich in einen Nginx-Controller integrieren und erleichtert dadurch das Konfigurieren von Produktionsumgebungen mit mehreren Hosts. Weitere Informationen finden Sie im Thema zum Skalieren auf mehrere Server (in der StrongLoop-Dokumentation).

Reverse Proxy verwenden

Ein Reverse Proxy befindet sich vor einer Webanwendung und führt Unterstützungsoperationen für die Anforderungen aus (außer das Weiterleiten von Anforderungen an die Anwendung). Er kann u. a. Fehlerseiten, Komprimierungen und Caching bearbeiten, Dateien bereitstellen und Lastverteilungen vornehmen.

Durch die Übergabe von Tasks, die keine Kenntnis des Anwendungsstatus erfordern, an einen Reverse Proxy muss Express keine speziellen Anwendungstasks mehr ausführen. Aus diesem Grund wird empfohlen, in Produktionsumgebungen Express hinter einem Reverse Proxy wie Nginx oder HAProxy auszuführen.