Webkrauts Logo

Webkrauts Webkrauts Schriftzug

- für mehr Qualität im Web

Serverseitiges JavaScript mit node.js

Serverseitiges JavaScript mit node.js

JavaScript hat sich in den letzten Jahren eindrucksvoll als Skriptsprache für Webbrowser etabliert. Doch ist die Sprache keineswegs auf clientseitige Anwendungen beschränkt. Ralf Graf stellt heute node.js vor: eine serverseitige Implementation von JavaScript, die ideal für anspruchsvolle Multi-User- und Echtzeit-Web-Anwendungen geeignet ist.

JavaScript kennt jeder Webworker. Was aber nicht jeder weiß: Ihr könnt JavaScript nicht nur wie gewohnt im Browser auf der Client-Seite verwenden, sondern auch auf der Server-Seite zur Erstellung von Web-Anwendungen. Das ist nicht unbedingt neu, es gibt z.B. schon länger die in Java implementierte JS-Engine Rhino, die u.a. in der bei Old-School-Bloggern beliebten Weblog-Engine und -Community Antville zum Einsatz kommt.

Richtig populär wurde serverseitiges JavaScript aber durch das 2009 von Ryan Dahl entwickelte node.js. Das ist ein JS-Framework auf Basis der von Google entwickelten V8-JavaScript-Engine, die in Googles Browser Chrome zum Einsatz kommt. Damit könnt ihr JS für beliebige serverseitige Aufgaben verwenden. Statt JS im Browser und eine weitere Sprache wie PHP, Ruby oder Python auf dem Server zu nutzen, können JS-Programmierer sich nun auf JavaScript beschränken. Alles, was mit den üblichen Server-Sprachen realisiert werden kann, kann node.js auch.

Ebenfalls möglich ist die Nutzung als kommandozeilen-basierter JS-Interpreter zur Ausführung von JavaScript außerhalb eines Browsers. Das nutzt z.B. die populäre JS-Meta-Sprache CoffeeScript, um CoffeeScript-Code in JavaScript zu kompilieren.

Eine Architektur für hohe Performance

Aber Node.js ist nicht nur ein »PHP-Ersatz in JavaScript«. Es wurde in einer »Event«-gesteuerten Architektur entwickelt und zeichnet sich deshalb durch eine hohe Performance aus, die mit PHP und Co. mit derselben Hardware nur schwer erreicht werden kann. Das zeigt sich besonders bei modischen, häufig zu aktualisierenden »Echtzeit-Web«-Anwendungen.

Was bedeutet das? Normalerweise sind Web-Frameworks und serverseitige Programmiersprachen »Thread«-gesteuert, d.h. einer oder mehrere Server-Prozesse stehen bereit und verarbeiten eine Aufgabe zu einer Zeit. Die Performance wird über die Anzahl der verfügbaren Threads begrenzt. Der Nachteil dabei: Wartet ein Thread gerade auf eine Datenbank oder muss auf die Platte schreiben, macht »er« in dieser Zeit nichts anderes, sondern blockiert die weitere Code-Ausführung bis diese Aktion beendet ist.

Node.js dagegen läuft normalerweise in einem Thread, der sich in einer endlos laufenden Ereignisschleife, der »Event-Loop«, befindet. Sämtliche Operationen der Anwendung laufen darin über so genannte »Callback-Funktionen« ab. Benötigt z.B. ein Request eine Datenbankabfrage oder liest von der Festplatte, so wird das im Hintergrund ausgeführt. Die »Event-Loop« registriert das und macht in der Zwischenzeit mit dem nächsten Request weiter. Ist die Datenbank-Abfrage fertig, so wird das über die Callback-Funktion an die »Event-Loop« gemeldet, und die nächsten notwendigen Schritte zur Auslieferung des Ergebnisses werden von dieser angestoßen. Das führt in der Praxis dazu, dass node.js sehr viele Anfragen quasi »parallel« verarbeiten kann, da es seine Zeit nicht mit unproduktiven Warten auf langsamere rechenintensive Prozesse in Subsystemen verschwendet.

Und was bringt uns das? Zusammen mit modernen Browser-Techniken wie WebSockets ermöglicht node.js das Erstellen hochperformanter Echtzeit-Multi-User-Web-Anwendungen. Beispiele sind das Multi-Player-Scrabble-Spiel wordsquared oder die kollaborative Schreibumgebung Etherpad Lite. Bei beiden Anwendungen müssen Ein- und Ausgaben vieler Benutzer parallel und in Echtzeit verarbeitet werden, was durch die ereignisgesteuerte Architektur von node.js mit vergleichsweise bescheidenen serverseitigen Hardware-Anforderungen realisiert werden kann.

Wenn Webworker gerne auch ihre serverseitigen Anwendungen in JavaScript programmieren möchten oder durch die Art der Anwendung hohe Anforderungen in Sachen »Echtzeit-Performance« haben, dann kann node.js das Werkzeug der Wahl sein.

Download und Installation

Node.js läuft auf unixoiden Systemen wie Mac OS X oder Linux, aber auch in der Cygwin-Umgebung unter Windows. Seit der Version 0.6.0 wird auch erstmals eine bereits kompilierte fertige »exe« für Windows angeboten. Es ist schlank und modular aufgebaut, bringt einige wichtige Kernmodule mit und hat mit npm einen Paketmanager zur Installation weiterer Module, ähnlich wie Rubygems für Ruby/Rails oder Pear bei PHP.

Auf dem Mac könnt ihr node.js auch mit dem Paketmanager Homebrew mit brew install node installieren.

»Hallo Welt« – Ein Webserver in node.js

Ein »hello.js« als Webserver – zum Ausprobieren einer neuen Sprache die obligatorischen Ausgabe von »Hello World« – sieht so aus:

  1. var http = require('http');
  2. http.createServer(function (req, res) {
  3.     res.writeHead(200, {'Content-Type': 'text/plain'});
  4.     res.end('Hallo Welt!\n');
  5. }).listen(1337, "127.0.0.1");
  6. console.log('Server running at http://127.0.0.1:1337/');

Diesen JS-Code schreibt der Webworker in eine Datei namens »hello.js« und führt sie mit node hello.js auf der Kommandozeile aus. Node.js startet das Programm hello.js, das ein vollwertiger Webserver auf Port 1337 ist. Lenkt er seinen Browser nun zu http://127.0.0.1:1337/, erscheint das »Hallo Welt« im Browser. Das Modul »http« wird mit node.js mitgeliefert und stellt eine komplette Webserver-Umgebung zur Verfügung.

Wiederverwendbarer Code

Neben der guten Performance liegt der Reiz von Node.js in der Möglichkeit der Wiederverwendbarkeit von Code. Wenn der Webworker für den Browser clientseitig sowieso JavaScript-Methoden schreibt, z.B. für eine ausgefeilte Formular-Validierung, kann er diese in Node.js auch serverseitig verwenden. Damit spart er sich also eine weitere Implementierung der Applikations-Logik in einer anderen Sprache (PHP und Co.) für den Server.

Und er kann vorhandene JS-Code-Bibliotheken wie jQuery verwenden. Mit npm install jquery wird das Modul heruntergeladen und kann in Node.js verwendet werden. Damit kann der Webworker dann Aufgaben bewerkstelligen wie serverseitig Informationen aus andere Website »scrapen« und DOM-Bäume mit den gewohnten jQuery-Methoden verarbeiten.

Links

Das war natürlich nur ein kleiner Einblick in diese interessante Technologie. Einige weiterführende Links:

Kommentare

Coco
am 13.12.2011 - 09:58

Na, das ist ein Zufall. Da hab ich doch gestern erst noch einen Blogartikel bei meinem Lieblingshoster DF gelesen (http://www.df.eu/blog/2011/12/12/node-js-bei-domainfactory/) und hab mir schon Gedanken über einen Einsatz von node.js gemacht.

Danke nochmal für Deinen interessante Artikel.

Permanenter Link

Dorothea Schäfer
am 15.12.2011 - 08:40

Wie glatt laufen denn Schnittstellen zum Dateisystem, Verarbeitung von XML und Webservices? Wie gehen die Datenbanken mit den parallelen Anfragen um? Spannend ist es allemal und das Paradigma klingt auch viel passender für das Web.

Permanenter Link
Ralf Graf

Ralf Graf (Autor)
am 15.12.2011 - 09:14

Für das Dateisystem gibt es ein hübsches Modul.

Mit XML hatte ich glücklicherweise in Sachen Node noch nix zu tun. Das Parsen von XML-Nodes ist ja letztendlich in keiner Sprache schön ;-), mein erster Versuch wäre wahrscheinlich das XML mit xml2js umzuwandeln.

Permanenter Link

Paul
am 15.12.2011 - 17:48

@Dorothea Schäfer: XML-Verarbeitung stellt kein Problem dar. Es gibt zahlreiche Implementierungen von Parsern und Generatoren. Viele Node.js-Programme setzen aber auf das einfachere JSON zum Datenaustausch.

Außerdem gibt es Module für alle wichtigen SQL- (MySQL, PostgreSQL, etc.) sowie NoSQL-Datenbanken (MongoDB, redis, etc.).

Einen guten Überblick über vorhandene Funktionalitäten bietet die Modules-Seite im Node.js-Wiki. Diese ist aber bei weitem nicht vollständig.

Permanenter Link

Jörg Strotmann
am 20.01.2013 - 23:31

Der Einsatzzweck wird sich meines Erachtens auf Applikationen beschränken die
viel Push / Pull Funktionalität und Asynchronität brauchen - wenn es denn stabil
läuft und die API Calls nicht abbrechen.

Permanenter Link

Die Kommentare sind geschlossen.