Vorteile von Orleans
Im Folgenden sind die Hauptvorteile von Orleans aufgelistet:
- Entwicklerproduktivität, auch für nicht erfahrene Programmierer.
- Transparente Skalierbarkeit standardmäßig ohne besonderen Aufwand vom Programmierer.
Entwicklerproduktivität
Das Orleans-Programmiermodell steigert die Produktivität von erfahrenen und unerfahrenen Programmierern, indem folgende Schlüsselabstraktionen, Garantien und Systemdienste bereitgestellt werden:
Bekanntes OOP-Paradigma (objektorientiertes Programmierparadigma)
Grains sind .NET-Klassen, die deklarierte .NET-Grainschnittstellen mit asynchronen Methoden implementieren. Grains erscheinen dem Programmierer als Remoteobjekte, deren Methoden direkt aufgerufen werden können. Dies bietet dem Programmierer das vertraute OOP-Paradigma, indem Methodenaufrufe in Nachrichten umgewandelt, an die richtigen Endpunkte weitergeleitet, die Methoden des Zielgrains aufgerufen und Fehler und Ausnahmefälle transparent behandelt werden.
Einzelthreadausführung von Grains
Die Runtime garantiert, dass ein Grain immer nur in einem Thread ausgeführt wird. In Kombination mit der Isolation von anderen Grains ist der Programmierer nie mit Parallelität auf der Grainebene konfrontiert und muss zum Steuern des Zugriffs auf freigegebene Daten keine Sperren oder andere Synchronisierungsmechanismen verwenden. Allein dieses Feature macht die Entwicklung verteilter Anwendungen für nicht erfahrene Programmierer nutzbar.
Transparente Aktivierung
Die Runtime aktiviert ein Grain nur, wenn eine Nachricht für die Verarbeitung vorhanden ist. Dadurch wird das Konzept der Erstellung eines Verweises auf ein Grain, das für Anwendungscode sichtbar und durch diesen gesteuert wird, und die physische Aktivierung des Grains im Arbeitsspeicher, die für die Anwendung transparent ist, sauber getrennt. Dies ist mit einem virtuellen Arbeitsspeicher insofern vergleichbar, als dass entschieden wird, wann ein Grain „ausgelagert“ (deaktiviert) oder „eingelagert“ (aktiviert) werden soll. Die Anwendung hat ununterbrochenen Zugriff auf den gesamten „Speicherplatz“ von logisch erstellten Grains, ganz gleich, ob diese sich zu einem bestimmten Zeitpunkt im physischen Speicher befinden.
Die transparente Aktivierung ermöglicht einen dynamischen, adaptiven Lastenausgleich durch Platzierung und Migration von Grains im Pool von Hardwareressourcen. Dieses Feature stellt eine erhebliche Verbesserung gegenüber dem herkömmlichen Akteurmodell dar, bei dem die Lebensdauer des Akteurs von der Anwendung verwaltet wird.
Speicherorttransparenz
Ein Grainverweis (Proxyobjekt), der vom Programmierer verwendet wird, um die Methoden eines Grains aufzurufen oder an andere Komponenten zu übergeben, enthält nur die logische Identität des Grains. Die Übersetzung der logischen Identität des Grains in den jeweiligen physischen Speicherort und das entsprechende Routing von Meldungen erfolgen transparent durch die Orleans-Runtime.
Der Anwendungscode kommuniziert mit Grains, ohne deren physischen Speicherort zu kennen. Dieser kann sich im Laufe der Zeit aufgrund von Fehlern oder wegen der Ressourcenverwaltung ändern oder weil ein Grain zum Zeitpunkt des Aufrufs deaktiviert ist.
Transparente Integration in einen persistenten Speicher
Orleans ermöglicht die deklarative Zuordnung des In-Memory-Zustands eines Grains zu einem persistenten Speicher. Updates werden synchronisiert, wodurch transparent sichergestellt wird, dass Aufrufer Ergebnisse erst erhalten, nachdem der persistente Zustand erfolgreich aktualisiert wurde. Das Erweitern und/oder Anpassen vorhandener Anbieter persistenter Speicher ist einfach.
Automatische Weitergabe von Fehlern
Die Runtime gibt nicht behandelte Fehler automatisch über die Aufrufkette mit der Semantik von asynchronem und verteiltem Try/Catch weiter. Daher gehen Fehler innerhalb einer Anwendung nicht verloren. Dadurch kann der Programmierer Fehlerbehandlungslogik an den entsprechenden Stellen platzieren, ohne dass die mühsame Arbeit der manuellen Weitergabe von Fehlern auf jeder Ebene erforderlich ist.
Standardmäßig transparente Skalierbarkeit
Das Orleans-Programmiermodell ist so konzipiert, dass es den Programmierer auf einen Weg führt, der bei der Skalierung einer Anwendung oder eines Diensts über mehrere Größenordnungen hinweg Erfolg verspricht. Dies geschieht durch die Einbeziehung bewährter Methoden und Muster sowie durch eine effiziente Implementierung der Systemfunktionen auf unterer Ebene.
Im Folgenden sind einige wichtige Faktoren aufgeführt, die Skalierbarkeit und Leistung ermöglichen:
Implizite differenzierte Partitionierung des Anwendungszustands
Durch die Verwendung von Grains als direkt adressierbare Entitäten schlüsselt der Programmierer implizit den Gesamtzustand seiner Anwendung auf. Das Orleans-Programmiermodell schreibt zwar nicht vor, wie groß oder klein ein Grain sein soll. Meist empfiehlt sich jedoch eine relativ große Anzahl von Grains (Millionen oder mehr), wobei jedes Grain eine natürliche Entität der Anwendung darstellt, z. B. ein Benutzerkonto oder eine Bestellung.
Da Grains einzeln adressierbar sind und ihr physischer Speicherort von der Runtime abstrahiert wird, verfügt Orleans über eine enorme Flexibilität beim Lastenausgleich und beim transparenten und generischen Umgang mit Hotspots, ohne dass der Anwendungsentwickler darüber nachdenken muss.
Adaptive Ressourcenverwaltung
Grains stellen keine Vermutungen zur Positionierung anderer Grains an, mit denen sie interagieren. Aufgrund dieser Speicherorttransparenz kann die Runtime die Zuteilung verfügbarer Hardwareressourcen dynamisch verwalten und anpassen. Hierzu trifft die Runtime als Reaktion auf Last- und Kommunikationsmuster differenzierte Entscheidungen im Hinblick auf die Platzierung und Migration von Grains im Computecluster, ohne dass eingehende Anforderungen fehlschlagen. Durch das Erstellen mehrerer Replikate eines bestimmten Grains kann die Runtime den Durchsatz des Grains erhöhen, ohne dass Änderungen am Anwendungscode erforderlich sind.
Multiplexkommunikation
Grains in Orleans haben logische Endpunkte, und das Messaging zwischen allen wird über eine feste Anzahl von physischen Verbindungen (TCP-Sockets) gemultiplext. Dadurch kann die Runtime Millionen adressierbarer Entitäten mit geringem Betriebssystemaufwand pro Grain hosten. Darüber hinaus fallen durch die Aktivierung und Deaktivierung eines Grains keine Kosten für das Registrieren/Aufheben der Registrierung eines physischen Endpunkts beispielsweise eines TCP-Ports oder einer HTTP-URL oder gar durch das Schließen einer TCP-Verbindung an.
Effiziente Planung
Die Laufzeit plant die Ausführung einer großen Anzahl von Singlethread-Aggregationsintervallen mithilfe des .NET-Threadpools, der in hohem Maße für die Leistung optimiert ist. Da Graincode im nicht blockierenden, fortsetzungsbasierten Stil geschrieben wird (eine Voraussetzung des Orleans-Programmiermodells), wird Anwendungscode in einer sehr effizienten „kooperativen“ Multithreadmethode ohne Konflikte ausgeführt. Dadurch ist es möglich, dass das System einen hohen Durchsatz erreicht und bei sehr hoher CPU-Auslastung (bis zu 90 % und mehr) mit großer Stabilität läuft.
Der Umstand, dass eine Zunahme der Anzahl der Grains im System und der Last nicht zu zusätzlichen Threads oder anderen Betriebssystemprimitiven führt, trägt zur Skalierbarkeit einzelner Knoten und des gesamten Systems bei.
Explizite Asynchronie
Das Orleans-Programmiermodell macht die asynchrone Natur einer verteilten Anwendung explizit und leitet die Programmierer dazu an, nicht blockierenden asynchronen Code zu schreiben. In Kombination mit asynchronem Messaging und effizienter Planung ermöglicht dies ein hohes Maß an verteilter Parallelität und einen hohen Gesamtdurchsatz ohne explizite Verwendung von Multithreading.