Echtzeitergebnisanzeige für Motorsportrennen mit JavaScript

Während eines laufenden Wettkampfs den Stand der Teilnehmer im Internet aktuell anzuzeigen ist eine größere Herausforderung, wenn viele Tausend Browser angeschlossen sind. Ein Projektbericht über die Livetiming-Website einer europäischen Motorsportrennserie zeigt, dass eine Umsetzung mit JavaScript sowohl auf dem Client als auch auf dem Server möglich ist.

In Pocket speichern vorlesen Druckansicht 4 Kommentare lesen
Lesezeit: 21 Min.
Von
  • Thomas Suer
  • Martin Möllenbeck
  • Dr. Holger Schwichtenberg
Inhaltsverzeichnis

Während eines laufenden Wettkampfs den Stand der Teilnehmer im Internet aktuell anzuzeigen ist eine größere Herausforderung, wenn viele Tausend Browser angeschlossen sind. Ein Projektbericht über die Livetiming-Website einer europäischen Motorsportrennserie zeigt, dass eine Umsetzung mit JavaScript sowohl auf dem Client als auch auf dem Server möglich ist.

Die Motorsportrennserie, für die das Livetiming modernisiert wurde, gilt als populärste Tourenwagen-Rennserie der Welt, in der sich gleich drei deutsche Premium-Automobilhersteller dem direkten Wettkampf stellen. Pro Kalenderjahr finden in der Rennserie zehn Automobilrennen in Europa statt. Neben deutschen Traditionsrennstrecken wie Hockenheim-, Nürburg- und Norisring werden Rennen in England, Österreich, den Niederlanden und Spanien ausgetragen. 22 Piloten aus zehn Nationen kämpfen um den Meistertitel.

An einem Rennwochenende finden vor dem eigentlichen Rennen zwei freie Trainings, vier Qualifikationsteile und ein Warm-up statt. Jedes Fahrzeug verfügt über einen eindeutigen Transponder zur Ermittlung von Sektor- und Rundenzeiten. Als Gegenstück sind auf jeder Rennstrecke drei Messschleifen installiert: eine bei Start/Ziel und zwei weitere für Sektoren zur Zwischenzeitnahme. So gibt es pro Fahrzeug und je gefahrene Runde insgesamt drei Zeiten. Die sogenannte Zeitnahme erfasst die Messsignale und wertet sie aus. Die ermittelten Zeiten dienen zur Klassifizierung der Fahrzeuge und stehen dem Fernsehen, Journalisten und den Teams als Information zur Verfügung. Typischerweise werden die ermittelten Zeiten auf Displays an die Kommandostände an den Boxenmauern, in den Garagen der Teams und im Mediacenter verteilt.

Während eines Rennwochenendes sind die aktuellen Zeitnahmeergebnisse und Rennstände aller teilnehmenden Fahrzeuge über eine Website abrufbar (s. Abb. 1). Verschiedene Farben bei der tabellarischen Darstellung der Zeitnahmedaten sollen helfen, bestimmte Zustände leichter zu erkennen. So präsentiert der Bildschirm die Fahrer, die sich in derselben Runde wie der Führende befinden, in weißer Schrift. Fahrer, die die Ziellinie noch nicht überfahren haben, also jene mit mindestens einer Runde Rückstand, erscheinen gelb gefärbt. Befindet sich ein Pilot beim oder auf dem Weg zum Boxenstopp, ist eine rote Färbung zu sehen. Die schnellsten Sektor- und Rundenzeiten eines Fahrers werden ebenfalls farbig hervorgehoben, grün bei persönlicher und pinkfarben bei absoluter Bestzeit. Neben den Zeiten laufen Informationen über die höchste erreichte Geschwindigkeit in einem Sektor und dem Fahrernamen auf, der sie erzielte. Für jedes Rennwochenende gibt es eigene Darstellungen, die angezeigten Daten und somit Spalten unterscheiden sich dadurch.

Aktuelle Rennstände (Abb. 1)

Die Renn-Website zeigte bislang die Zeitnahmetabelle in einer sich zyklisch aktualisierenden Webseite an, die serverseitig mit PHP erzeugt wurde. Das Zeitnahmesystem generierte eine CSV-Datei, die der Webserver mit PHP auslas und aufbereitete. Alle 30 Sekunden riefen alle aufgeschalteten Clients, das heißt Webbrowser, per AJAX-Polling die aktuellen Werte vom Webserver ab.

Die Rundenzeiten liegen bei den meisten befahrenen Rennstrecken bei deutlich über einer Minute, sodass die langen Aktualisierungsintervalle akzeptabel waren. Auf einer Rennstrecke, Brands Hatch in England, liegt die Rundenzeit jedoch mit circa 42 Sekunden deutlich unter einer Minute. Der Umstand führte zu erheblichen Differenzen zwischen der realen Position, der Rundenanzahl und -zeit eines Fahrzeugs und der eigentlichen Visualisierung. Im schlimmsten Fall hinkte die Anzeige auf der Website eine knappe Runde hinterher, wenn sich der Browser knapp vor Erreichen einer Messschleife aktualisierte. Dann durchfuhr das Fahrzeug die nächsten beiden Zeitschleifen ohne entsprechende Aktualisierung der Webseite. Daraus ergab sich der Bedarf, eine Echtzeitanwendung zu schaffen.

Die wichtigsten Anforderungen an die neue, "Livetiming" genannte Entwicklung waren:

  • schnellstmögliche Aktualisierung der beiden Sektoren- und der Rundenzeiten
  • Unterstützung vieler unterschiedlicher Endgeräte und Betriebssysteme
  • kein Neuladen der gesamten Seite bei Aktualisierung der Daten
  • zuverlässige Anbindung und Versorgung vieler Clients (Skalierbarkeit)
  • Vermeidung einer clientseitigen Installation von Software
  • einfache, schnelle und kostengünstige Implementierung, bedingt durch engen Zeitplan und Budgetgrenzen
  • niedrige Lizenzkosten bei den eingesetzten Komponenten

Eine spannende Frage war die der einzusetzenden Technik. Ein Blick in die Königsklasse des automobilen Motorsports, die Formel 1, zeigte eine seit Jahren eingesetzte Technik mit Java-Applet und Sockets. Ein gravierender Nachteil bei einer Java-Anwendung ist jedoch, dass auf jedem Client die Java Runtime Environment (JRE) installiert sein muss. Das erscheint jedoch nicht mehr zeitgemäß, insbesondere vor dem Hintergrund, dass Besitzer von Mobiltelefonen oder Tablet-PCs die Installation häufig nicht wünschen oder ihr Gerät Java gar nicht unterstützt.

Es war also eine Technik gefragt, die ohne Zusatzinstallationen auf allen Endgeräten lauffähig ist und Echtzeitaktualisierungen unterstützt. Nach ausführlicher Erörterung fiel die Entscheidung auf eine HTML5 Webanwendung, die sowohl client- als auch serverseitig JavaScript verwendet und die Daten via REST API und WebSockets transportiert. Als Abstraktion von JavaScript sollte CoffeeScript zum Einsatz kommen.

Abbildung 2 zeigt die Architektur der neuen Anwendung. Die Zeitnahme liefert die Messdaten im Push-Betrieb nun in einem kontinuierlichen XML-Datenstrom an den Hauptserver, der die Messdaten verarbeitet, sobald ein Datensatz vollständig vorliegt. Der Hauptserver sichert die Messdaten in einer Datenbank und informiert die Anwendungsserver über neue Daten.

Architektur der neuen Anwendung

Die Webbrowser fragen über eine REST API beim Hauptserver an, der die Anfragen über einen Load-Balancer (haproxy) an mehrere Anwendungsserver weitergibt. Diese holen sich die aktuellen Daten aus der Datenbank und liefern sie über den Lastverteiler an die Clients. Im Folgenden informieren die Anwendungsserver die verbundenen Clients über das Vorliegen neuer Daten, sodass die Clients diese wieder abfragen. Der Hauptserver übernimmt die Verarbeitung der Zeitnahmedaten und beherbergt den haproxy; die Anwendungsserver bedienen über diesen die Clients mit Benachrichtigungen über neue Daten und liefern auf Anfrage die aktuellen (Abb. 2).

Als Kerntechnik kommt Node.js zum Einsatz, um somit die Vorteile der leichtgewichtigen Entwicklung mit JavaScript/CoffeeScript auszuschöpfen. Deren Einsatz auf Client, Server und Datenbank hat den Vorteil, dass es zwischen den Layern keinen Bruch bei der eingesetzten Programmiersprache gibt. Es kann bei der Datenvalidierung der gleiche Code auf dem Client und dem Server eingesetzt werden. Der Einsatz von Express.js als Framework für die Serverentwicklung gibt einen direkten Zugriff auf die HTTP-Methoden, was bei einer REST-API hilfreich und eine schnelle Entwicklung, ohne unnötigen Overhead, ermöglicht.

Nicht minder wichtige Vorzüge von Node.js sind der geringe Speicherbedarf und die ereignisorientierte Arbeitsweise. Der Datenstrom vom Zeitnahmeserver erfolgt in XML, das mit dem ORM-Mapper Mongoose als JSON in der eingesetzten MongoDB persistiert wird, die JSON-Dokumente (bzw. Binäres JSON, kurz BJSON) nativ ablegen kann. Die für das Konvertieren von XML nach JSON verantwortliche Bibliothek ist libxml (Package libxml-to-js). Für das Publishing, das heißt die Datenversorgung der Appserver, kommt Redis zum Einsatz, das über ein leistungsfähiges Publish-/Subscribe-Protokoll verfügt. Die Appserver wiederum aktualisieren die aufgeschalteten Browser-/Mobile-Apps in Echtzeit durch den Einsatz von Socket.io.

Ursprünglich stand für das Benachrichtigen der Clients allein das W3C-WebSocket-Protokoll (RFC 6455) im Raum. Grundsätzlich könnte der Server damit die Daten per Push an die Clients versenden, jedoch stünden dann Benutzer älterer Browser außen vor. Internet Explorer vor Version 10, Firefox vor Version 11, Chrome vor Version 16, Safari vor Version 6 und Opera vor Version 12.1 unterstützen RFC 6455 nicht oder nur eine Vorabversion.

An der Stelle bietet sich der Einsatz der JavaScript-Bibliothek Socket.io an, die selbstständig – ohne die API ändern zu müssen – auf eine für die Übertragung bestmögliche Technik umschalten kann. Socket.io verwendet alternativ zu WebSocket bei Bedarf Adobe Flash Socket, AJAX Long Polling, JAX Multipart Streaming, Forever Iframe oder JSONP Polling. Mit Heartbeats, Time-outs und Disconnection-Unterstützung komplettiert Socket.io den Umfang wichtiger Funktionen für die Konnektivität.

Auf Seiten der Benutzeroberfläche bietet Backbone.js ein einfaches MVC-Framework für Single-Page-Apps: Eine Änderung der Daten, also des Modells, erkennt der Controller, er signalisiert das in der Folge der HTML-View und stößt deren visuelle Aktualisierung, also das Rendern, neu an.

Twitter Bootstrap, ein CSS3-Framework, sorgt dafür, bestimmte Daten endgeräteabhängig entweder anzuzeigen oder zu unterdrücken, ein wichtiger Beitrag für die Umsetzung der Oberfläche, und rundet die Webanwendung auf der Clientseite ab. In Abhängigkeit des Endgeräts blendet Bootstrap bestimmte Spalten aus, um die Anwendung an die eingeschränkte Breite des Bildschirms anzupassen.

Das Stichwort an der Stelle lautet Responsive Design. Es wird selbstständig die für das jeweilige Endgerät definierte GUI-Ausprägung verwendet, ohne spezifische Softwareadaptionen bereitstellen zu müssen. Hochauflösende Desktops sind so ebenso abgedeckt wie niedrig auflösende Smartphones. Der folgende Codeschnipsel zeigt den Einsatz von Bootstrap in Verbindung mit den Templates aus Underscore.js. Daraus ist erkennbar, dass die explizite Verwendung der CSS-Klasse hidden-phone die Spalten start_number (Startnummer), name (vollständiger Name des Piloten), interval (Rückstand zum Vordermann) und last_lap (letzte Rundenzeit des Piloten) auf Mobiltelefonen ausblendet (s. Abb. 3).

td.race(id="position")
| <%= timing.line %>
td.race.hidden-phone(id="start_number")
| <%= driver.number %>
td.race.hidden-phone(id="name")
| <%= driver.first_name %>&nbsp;<%= driver.last_name %>
td.race(id="short_name")
| <%= driver.slug %>
td.race(id="lap_count")
| <%= timing.laps %>
td.race(id="total_time")
| <%= timing.total_time %>
td.race(id="gap")
| <%= timing.distance_gap %>
td.race.hidden-phone(id="interval")
| <%= timing.distance_interval %>
td.race(id="sec1")
| <%= timing.section_1_time %>
td.race(id="sec2")
| <%= timing.section_2_time %>
td.race(id="sec3")
| <%= timing.section_3_time %>
td.race.hidden-phone(id="last_lap")
| <%= timing.time_last_lap %>
td.race(id="number_of_stops")
| <%= timing.number_of_stops %>

Die Webseite im Mobiltelefon: Twitter Bootstrap blendet gezielt Spalten aus, um Platz zu sparen (Abb. 3).

Die Anwendung wurde nach dem Prinzip des Test Driven Development (TDD) entwickelt. Das heißt, jede neue Funktion wurde durch entsprechende Tests überprüft. Das eingesetzte Testframework ist Mocha.js. Hier ein beispielhafter Unit-Test:

assert = require 'assert'
auth_helper = require "#{__dirname}/../../lib/auth_helper"

describe "auth helper", ->

it "should generate a salt", ->
salt = auth_helper.generate_salt()
assert.ok salt.length > 0

it "should generate the crypt password", ->
salt = auth_helper.generate_salt()

first_password = auth_helper.crypt_password("password", salt)
second_password = auth_helper.crypt_password("password", salt)

assert.equal first_password, second_password

Und der zu testende JavaScript-Code:

crypto = require('crypto')

sha = (num) ->
secureDigest = (salt, digest, password, pepper) ->
ret = crypto.createHash('sha' + num)
.update('--' + Array.prototype.join.call(arguments, '--') + '--')
.digest('hex')
ret

return {
digest: (password, stretches, salt, pepper) ->
digest = pepper
while (stretches--)
digest = secureDigest(salt, digest, password, pepper)
return digest
}

class AuthHelper

@pepper = "mind-assist"
@sha = sha(512)

@generate_salt: () ->
len = 15
set =
'0123456789abcdefghijklmnopqurstuvwxyzABCDEFGHIJKLMNOPQURSTUVWXYZ'
setLen = set.length
salt = ''

while salt.length <= len
p = Math.floor(Math.random() * setLen)
salt += set[p]

salt


@crypt_password: (password, salt) ->
@sha.digest(password, 1, salt, @pepper)


module.exports = AuthHelper

Für den Test der Anwendung vor dem eigentlichen Betrieb fanden bei früheren Rennveranstaltungen Datenmitschnitte des freien Trainings, der Qualifikation, des Warm-ups und des Rennens statt. Die erfassten Datenströme wurden als XML-Dateien gespeichert und standen sodann einem Simulationsserver zur Verfügung. Dieser liest die XML-Dateien, das heißt reale Daten, ein und versendet sie nacheinander in konfigurierbaren Zeitintervallen. Eine Lasterhöhung und somit ein Stresstest ließ sich durch ein Verkürzen der Zeitintervalle herbeiführen.

Durch die der Realität entnommenen Testdaten fiel eine Besonderheit auf, die nicht in den Anforderungen dokumentiert war. In der Startphase eines Rennens sind die Fahrzeuge dicht beieinander und überfahren in entsprechend kurzen Zeitabständen (teilweise weniger als 100 ms) die Messschleifen. Jede Überfahrt eines Fahrzeugs erzeugt ein Signal, das den Zeitnahmeserver zum Versand des gesamten Klassements veranlasst. Das Gesamtklassement umfasst sämtliche Daten über Position, Startnummer, Fahrzeug, Pilot, Abstand zum Führenden, Abstand zum Vordermann, Sektorzeiten, Rundenzeit und die Anzahl der Boxenstopps jedes einzelnen Fahrers.

Die Livetiming-Anwendung wiederum generiert aus den empfangenen Daten ebenfalls Benachrichtigungen und versendet sie an alle registrierten Clients. Da die Aktualisierungszeit der Clients (Laden der Daten und Rendern der HTML-Views) teilweise länger dauerte als die Zeitabstände der Fahrzeuge untereinander, wurden bereits neue Daten an die Clients gesendet, obwohl sie die zuvor gesendeten Daten unter Umständen noch gar nicht verarbeitet und visualisiert hatten. Das führte schlimmstenfalls dazu, dass sich auch Browser Events (z. B. Verändern der Größe des Browser-Fensters) nicht schnell abarbeiten ließen und die gesamte Anwendung ausgesprochen träge wirkte.

Abhilfe verschaffte die Änderung der Strategie vom Push-Betrieb auf Push-/Pull-Betrieb. Das bedeutet, dass bei Empfang neuer Daten die Livetiming-Anwendung nun nicht mehr das gesamte Klassement an alle Clients versendet, sondern diese lediglich über das Vorhandensein neuer Daten informiert. Jeder Client entscheidet dann für sich, ob er für neue Daten empfänglich ist, und fordert diese explizit als AJAX-Request an. Die Serverkomponente liefert darauf die neuesten Daten. Sollten zwischen dem Zeitpunkt der Client-Anfrage und dem Versenden bei der Serverkomponente neue Daten vom Zeitnahmeserver eingetroffen sein, versendet die Serverkomponente die aktualisierten Daten und nicht jene, die zum Zeitpunkt der Client-Anfrage aktuell waren. In diesem Szenario erhält der Client keine Benachrichtigung über neue Daten, da ihm ohnehin die neuesten Daten geliefert werden.

Trotz der intensiven Tests mit realen Daten im Vorfeld zeigten sich beim ersten Einsatz der neuen Webanwendung in einem realen Rennen weitere Schwachstellen, die erst durch die Vielzahl verbundener Clients sichtbar wurden und sich somit nicht bei vorangegangenen Tests aufdecken ließen. Die Livetiming Anwendung nahm in 80 Minuten, die das Rennen inklusive Vor- und Nachlauf dauerte, insgesamt sechs GByte Daten vom Zeitnahmeserver entgegen und verarbeitete sie. Währenddessen versendete die Serverkomponente 24 GByte Daten an etwa 3200 Clients. Bei einer Gesamtsumme von circa 3.400.000 Requests wurden je Client rund 1000 Requests und eben so viele Notifications abgearbeitet. Die im ersten Rennen erhobenen Statistiken fungierten als Indikator für notwendige Optimierungen und Verbesserungen.

Geplant war, maximal 2000 Clients zu versorgen, es waren jedoch im ersten Rennen bis zu 3200 Clients an das Livetiming angebunden und sorgten für Datenmengen, die nicht zu bewältigen waren. Das war unter anderem dem Umstand geschuldet, dass einige der vier beim ersten Rennen eingesetzten Appserver aufgrund eines Fehlers in der Socket.io-Bibliothek ihren Dienst versagten. Zudem kam es aufgrund einer langsamen Internetverbindung bei den Clients zum Fallback von WebSocket auf Long-Polling.

Die Erkenntnisse aus den Analysen des ersten Rennens deckte also weiteres Optimierungs- und Verbesserungspotenzial auf: Die zu übertragene Datenmenge wurde für die API-Daten reduziert. Das erfolgte im REST-Aufruf durch Wegfall nicht benötigter Felder und Verkürzung von Feldinhalten. Die von Socket.io für Redis genutzte Serialisierung ist JSON.stringify (Serialisierung) und JSON.parse (Deserialisierung). Beides hat sich in der Praxis als relativ langsam herausgestellt. Mit dem Serialisierungsformat MessagePack, das in der Verwendung ähnlich einfach wie die JSON-Serialisierung ist, wurde eine schnellere und schlankere Alternative gefunden. Der Speicher- und CPU-Bedarf wurde so optimiert.

Einige Missstände waren auf einen Fehler in der Socket.io-Bibliothek zurückzuführen. Mit Installation der neuesten und mit einigen Bugfixes ausgestatteten Version waren die Fehler nicht mehr zu beobachten. Die Anzahl der Datenbankabfragen wurde ebenfalls reduziert, das heißt identische Abfragen unterdrückt.

Das alte Datenmodell machte bei Empfang neuer Daten des Zeitnahmeservers aufgrund separater Datensätze 23 Schreiboperationen notwendig: Eine Schreiboperation für die Informationen über beste Rundenzeit, Geschwindigkeit etc. und für jeden Fahrer (22) je einen Datensatz mit Informationen über Position, Startnummer, Pilot, Zeiten, Rundenzeit et cetera sowie eine weitere zur Aktualisierung der ersten Informationen.

Analog verhielt es sich dann beim Auslesen, das heißt dem Weiterreichen der Daten an die Clients. Dann wurden 23 Leseoperationen durchgeführt: eine zu den Informationen über beste Rundenzeit usw. und 22 über die Rundeninformationen jedes Fahrers.

Das überarbeitete Datenmodell tätigt nur noch genau eine Schreiboperation bei eintreffenden Daten vom Zeitnahmeserver: die Informationen zu bester Rundenzeit etc. und ein Array der fahrer- und rundenspezifischen Informationen (Position, Pilot, Zeiten etc.). Dementsprechend wird beim Transfer der Daten an die Clients ebenfalls nur noch eine Leseoperation benötigt. Die gesamte Verarbeitung, beginnend beim Eintreffen neuer Daten vom Zeitnahmeserver, bis hin zur Aktualisierung der Client-Daten, wurde somit schlanker und effektiver.

Für die kommende Saison sind einige inhaltliche Erweiterungen der neuen Webanwendung angedacht, zum Beispiel die Integration des Livetickers, über den Journalisten das Renngeschehen dokumentieren. Er nutzt derzeit noch die alte Technik.

Der Zeitnahmeserver versendet auch von der Rennleitung ausgehende Hinweise, zum Beispiel zu welcher Uhrzeit die Boxenampel auf Grün geschaltet wird oder wenn das Safetycar auf die Strecke geht oder Strafen ausgesprochen werden. Diese Daten wären in die Livetiming-Anwendung zu integrieren und entsprechend zu visualisieren.

Die Livetiming-Anwendung besitzt Informationen über das Ergebnis vorhergegangener Rennen der Saison und somit auch über die Meisterschaftstabelle. Kombiniert mit den Platzierungen der Piloten im aktuellen Rennen ließe sich daraus eine Live-Meisterschaftstabelle berechnen und anzeigen und somit ein weiteres Spannungselement erzeugen.

Die Positionsdaten eines Fahrzeugs lassen sich mit GPS-Empfänger ermitteln, an die Zeitnahme übertragen und der Livetiming-Anwendung zur grafischen Anzeige auf einer Streckenkarte zur Verfügung stellen (Livetracking). In einer solchen Übersicht sind mögliche Positionskämpfe (auch anstehende Überrundungen) und Boxenstopp-Situationen schneller zu erkennen.

Eine Zeitnahme wird grundsätzlich von jeder Rennserie und jedem Wettbewerb benötigt, der Zeiten zur Klassifizierung nutzt. Insofern könnte die Livetiming-Anwendung darüber hinaus nicht nur für weitere Rennserien, sondern auch für andere Sportveranstaltungen mit Zeitnahme zum Einsatz kommen.

Auch im Bereich der Softwarearchitektur gibt es noch Pläne. Das Fehlen einer Ausfallsicherheit im Bereich des Hauptservers und der Datenbanken birgt derzeit noch die große Gefahr eines Totalausfalls der Anwendung. Die Überlegung geht in die Richtung, MongoDB Replicaset (also ein spezielles Cluster
für MongoDB), zu verwenden, also die Spiegelung der Daten auf einen zweiten Server. Neben einer erhöhten Ausfallsicherheit brächte das weitere positive Aspekte mit sich: Die Daten ließen sich von zwei Servern lesen (Performance), und als logische Konsequenz wäre zur optimalen Ressourcennutzung auch eine Lastverteilung (Loadbalancing) möglich.

Alternativ zu Redis ist RabbitMQ angedacht. Echtes Messaging auf Basis des AMPQ-Standards (Advanced Message Queuing Protocol), Subscribe/Publish inklusive Routing durch eines der beiden Kommunikationsverfahren (Topic Exchange bzw. Fan-out) wären die wichtigsten Vorteile. Außerdem bietet RabbitMQ eine höhere Performanz im Bereich Subscribe/Publish und benötigt keine Punkt-zu-Punkt-Verbindung. Letzteres würde eine gute Integration eines Tracing/Logging ermöglichen, ohne eine Änderung des Anwendungs-Codes zu bedingen. Die Daten für die Archivierung ließen sich dann über Nachrichten austauschen.

Das Deployment für die eingesetzten Server (zehn Appserver und ein Hauptserver) findet zurzeit manuell statt. Eine Umstellung auf das skriptbasierte Webdeployment-Werkzeug Capristano würde diesen Prozess vollständig automatisierbar und weniger fehleranfällig werden lassen. Die von Capristano durchgeführten Schritte sind:

  • Check-out des aktuellen Codes in ein neues Verzeichnis
  • Herunterfahren der Server
  • Umschaltung auf eine neue Codebasis
  • Start der Server

Im Fehlerfall erfolgt ein Fallback auf den vorherigen Code. Weitere Server werden durch simple Aufnahme in die Liste der Server hinzukonfiguriert.

Eine Meisterschaft besteht aus einer festgelegten Anzahl Rennen, die allesamt zeitlich abgegrenzte Veranstaltungen von definierten Zeitdauern sind. Konkret bedeutet das: Nur an zehn Wochenenden im Jahr besteht der Bedarf nach solcher Rechenleistung. Es ist also unwirtschaftlich, eine für die Spitzenzeiten der Rennwochenenden abgestimmte teure Hardwarekonfiguration zu kaufen oder zu mieten. Die Betriebskosten wären durch den Einsatz einer Platform as a Service zu minimieren. Mit Skalierung der Anzahl eingesetzter Appserver lässt sich der sich ändernden Anzahl Clients effektiv begegnen. Denkbare Produkte sind Heroku und Windows Azure, weil beide sowohl Node.js als auch den Betrieb einer MongoDB-Datenbank unterstützen.

Das beschriebene Projekt der Livetiming-Website bewies eindrucksvoll, dass die eingesetzten, auf JavaScript zentrierten Techniken und Bibliotheken trotz ihres jungen Alters einen guten Reifegrad erreicht haben und selbst zeit- und ressourcenkritische Anwendungen in einem ansprechenden Zeitraum realisierbar sind. Ferner zeigt es, dass sich die Technik auch für die Verarbeitung von Massendaten und die Versorgung vieler Clients durch die Möglichkeiten von Skalierung (Verteilung auf mehrere Appserver) eignet. Dass die Wahl der richtigen und passenden Techniken wichtig ist, wird bei Betrachtung der relativ kurzen Realisierungszeit für das Projekt von 30 Manntagen deutlich. Daher wurde auch viel Augenmerk darauf gelegt, sowohl auf Client- als auch auf Server- und Datenbankseite dieselbe Programmiersprache (JavaScript) einsetzen zu können. Etwaige Interoperabilitätsprobleme wurden so von vornherein minimiert.

Thomas Suer, Martin Möllenbeck und Dr. Holger Schwichtenberg
entwickeln hochskalierbare Enterprise-Anwendungen mit .NET und modernen Webtechniken bei der 5minds IT-Solutions GmbH & Co. KG.
(ane)