Donnerstag, 12. März 2015

Eine Einführung

Node.js

Der Einsatz von Node.js klingt verlockend, insbesondere, wenn man die Erfolgsmeldungen großer Early-Adopter liest: Ebay, PayPal, LinkedIn, Netflix, uvm.

Kurze Entwicklungszeiten, rasante Performance, geringe Latenz und gute Erweiterbarkeit. Doch nicht für jeden Zweck ist Node.js die perfekte Wahl.

Was ist Node.js?

Node.js ist eine Plattform für Netzwerkanwendungen, die insbesondere für die Verwendung als leichtgewichtiger Webserver eingesetzt wird. Sie nutzt die äußerst performante JavaSkript-Engine V8, die von Google für den Chrome-Browser entwickelt wurde. Außerdem bietet sie mit dem NPM einen Modulmanager, der sowohl die Modularisierung eigener Anwendungen als auch die Verwendung der vielen bereits frei verfügbaren Module erlaubt.

Welche Vorteile bringt Node.js?

Module

Entwicklungszeit und Robustheit haben sehr viel mit Wiederverwendbarkeit zu tun. Bausteine oder Module einer Software, die nicht jedes mal neu erfunden werden müssen, sondern einfach in einer vielfach getesteten Version zur Verfügung stehen, ermöglichen die Konzentration auf die tatsächlichen Schwerpunkte der aktuellen Anwendung. Mit Hilfe vieler von Node bereitgestellter Core-Module und tausenden Erweiterungsmodule steht ein ganzer Baukasten zur Verfügung.

Darüber hinaus ermöglicht der modulare Aufbau, dass eigene Applikationen und Teilapplikationen als Module entwickelt und wiederverwendet werden und somit Synergieeffekte genutzt werden können.

Sehr viele gleichzeitige Anfragen

Ein sehr großer Vorteil liegt in der asynchronen und damit nahezu blockadefreien Abarbeitung der Server-Anfragen. Während klassische Webserver pro Anfrage einen eigenen Thread starten, läuft bei einem Node.js-Server nur ein einziger. Was zunächst nach einem Nachteil klingt, offenbart sich als Vorteil, wenn man die Art der Abarbeitung genauer betrachtet.

Abbildung 1

Klassische Webserver (Abbildung 1, links) starten pro Anfrage einen Thread, arbeiten die Anfrage ab und geben eine Antwort zurück. Diese Abfrage erfolgt synchron, so dass der Thread so lange besteht und geblockt ist, bis Abarbeitung und Antwort abgeschlossen sind. Mit Hilfe von Multithreading auf Mulit-Core-Servern können so gleichzeitig tausende Anfragen beantwortet werden.

Dieser Ansatz birgt bei sehr vielen Anfragen Probleme:

  • Jeder Thread belegt automatisch Arbeitsspeicher, so dass mit steigender Thread-Anzahl immer mehr Arbeitsspeicher in Anspruch genommen wird.

  • Die Synchronisierung vieler Threads beansprucht ebenfalls Ressourcen.

  • die Anzahl der verfügbaren Threads aus dem Threadpool ist begrenzt

In der Folge können Arbeitsspeicher oder Prozessorleistung bei vielen Anfragen (Abbildung 1, links: A) an ihre Grenzen stoßen, was sich wiederum negativ auf die Performance und Antwortzeiten auswirkt. Weitere Anfragen müssen warten (Abbildung 1, links: B). Das ist besonders ineffektiv, wenn Threads eigentlich nur auf Abfragen des Dateisystems oder der Datenbank warten.

All dem kann mit vernünftiger Konfiguration und ggf. Aufstockung der Hardware entgegengewirkt werden, aber mit steigenden Zugriffszahlen steigen die Vorteile einer nicht-blockierenden Alternative wie Node.js.

Ein Node.js-Server arbeitet mit nur einem Thread, der in einer Schleife (Event Loop) nur auf Events wie Anfragen oder Antworten reagiert (Abbildung 1, rechts). Die Schleife übernimmt ausschließlich die Verwaltung der Aufgaben. Jede Abfrage von Daten aus Datenbanken oder dem Dateisystem, Berechnung oder sonstige Aufgaben wird asynchron bearbeitet. Dadurch ist die Event Loop jederzeit frei für weitere Anfragen und es kommt zu keiner Blockierung durch die I/O.

Anwendungsgebiete

  • hochfrequentierte Webseiten

Echtzeitanwendungen

Abbildung 2

Anwendungen, bei denen die Benutzer in Echtzeit mit neuen Daten versorgt werden müssen, lassen sich auf Grund der Zustandslosigkeit des HTTP/HTTPS-Protokolls nur über Umwege realisieren, da die Kommunikation vom Server zum Client immer nur als Antwort auf eine Frage vom Client erfolgt.

Um eine echte bidirektionale Kommunikation zu ermöglichen, wurde das WebSocket-Protokoll entworfen (Abbildung 2). Dabei wird die Verbindung nur ein mal vom Client geöffnet und kann anschließend von beiden Seiten aktiv genutzt werden. Neue Daten können so nahezu latenzfrei vom Server an den Client übergeben werden.

Es gibt viele Node.js-Module, die die Nutzung von WebSockets unterstützen und somit eine Echtzeit-Webanwendung möglich machen.

Anwendungsgebiete

  • Darstellung von Finanz-/Börsendaten

  • Übertragung von Spielständen/Newstickern

  • Spiele

Streaming

Data-Streaming gilt als eine der Stärken von Node.js. Dafür stellt die Plattform ein das Stream-Modul zur Verfügung, das als eine zentrale, leicht verständliche Schnittstelle dient. Diese wird auch von anderen Modulen verwendet, so dass eine einheitliche Nutzung von lesenden und schreibenden Datenströmen in der gesamten Anwendung möglich ist. Dabei übertragen sich die Vorteile der Event-getriebenen, asynchronen Architektur auch auf die Streams bzw. werden dort fortgeführt. Im Zuge der Versions-Updates 0.10 und 0.12 wurde das Modul noch mal in puncto Performance und Handhabung verbessert (Streams 2 und Streams 3).

Genutzt wird das Stream-Modul z.B. im http-, Net- oder FileSystem-Modul. Egal ob Netzwerkkommunikation über HTTP, TCP, UDP oder dateibasierte Kommunikation über UNIX-Sockets und Windows-Pipes: genutzt wird immer eine Implementierung des zentralen Stream-Moduls. Das schafft Einheitlichkeit und vereinfacht die Handhabung für Entwickler.

Beispiele

  • Audio-Streaming

  • Video-Streaming

  • Daten-Streaming

Wann ist Node.js nicht die richtige Wahl

Durch die Vielseitigkeit von Node.js gibt es kaum Anwendungsfälle, die gegen den Einsatz von Node.js sprechen. Allerdings rechtfertigen die Vorteile in bestimmten Fällen nicht die zwingende Verwendung.

Nutzlos sind die genannten Vorteile von Node.js bei Client-Anfragen, die auf dem Server synchrone Vorgänge auslösen. In diesem Fall sind schlechte Antwortzeiten zu erwarten.

Ebenso bringt Node.js keine Vorteile bei rechenintensiven/zeitintensiven Abfragen, da hier auch trotz asynchroner Abarbeitung keine schnellere Antwort zu erwarten ist. In diesem Fall ist die Optimierung der Berechnung/Abfrage eine bessere Variante.

Ob sich der Umstieg einer bestehenden Webseite/Webapplikation auf Node.js lohnt, ist individuell abzuwägen. Für Anwendungen mit bereits zufriedenstellender Performance, für die auch in Zukunft keine höheren Zugriffszahlen zu erwarten sind und deren Weiterentwicklung eher aus kleinen Änderungen besteht, ist ein Wechsel des Technologie-Stacks wahrscheinlich nicht die richtige Lösung.  


comments powered by Disqus