Freigeben über


Warum Datenströme in Orleans?

Für den Bau von Datenstromverarbeitungssystemen gibt es bereits eine Vielzahl von Technologien. Dazu gehören Systeme zum dauerhaften Speichern von Datenstromdaten (z. B. Event Hubs und Kafka) und Systeme zum Ausdrücken von Computevorgängen über Datenstromdaten (z. B. Azure Stream Analytics, Apache Storm und Apache Spark Streaming). Dies sind großartige Systeme, mit denen Sie effiziente Datenstromverarbeitungspipelines erstellen können.

Einschränkungen bestehender Systeme

Diese Systeme eignen sich jedoch nicht für feinkörnige Freiformberechnungen über Datenstrom. Mit den oben erwähnten Streaming-Computesystemen können Sie ein einheitliches Datenflussdiagramm von Vorgängen angeben, die auf die gleiche Weise auf alle Streamelemente angewendet werden. Dies ist ein leistungsfähiges Modell, wenn Daten einheitlich sind und Sie dieselbe Gruppe von Transformations-, Filter- oder Aggregationsvorgängen für diese Daten ausdrücken möchten. In anderen Anwendungsfällen müssen jedoch grundsätzlich unterschiedliche Vorgänge über verschiedene Datenelemente ausgedrückt werden. In einigen dieser Fälle müssen Sie im Rahmen der Verarbeitung gelegentlich einen externen Aufruf ausführen, z. B. das Aufrufen einer beliebigen REST-API. Einheitliche Datenfluss-Datenstromverarbeitungsmodule unterstützen diese Szenarien entweder nicht, unterstützen sie auf begrenzte und eingeschränkte Weise oder sind bei der Unterstützung ineffizient. Dies liegt daran, dass sie inhärent für ein großes Volumen ähnlicher Elemente optimiert sind und in der Regel in Bezug auf Ausdrucksfähigkeit und Verarbeitung eingeschränkt sind. Orleans Datenströme zielen auf diese anderen Szenarien ab.

Motivation

Alles begann mit Anfragen von Orleans Benutzern zur Unterstützung der Rückgabe einer Reihe von Elementen aus einem Grain-Methodenaufruf. Wie man sich vorstellen kann, war das nur die Spitze des Eisbergs; sie brauchten viel mehr.

Ein typisches Szenario für Orleans Streams ist, wenn Sie über Datenströme pro Benutzer verfügen und unterschiedliche Verarbeitungen für jeden Benutzer im Kontext dieses einzelnen Benutzers ausführen möchten. Möglicherweise haben Sie Millionen von Benutzern, aber einige interessieren sich für Wetter und abonnieren Wetterwarnungen für einen bestimmten Ort, während andere an Sportveranstaltungen interessiert sind; Eine andere Person kann den Status eines bestimmten Flugs nachverfolgen. Die Verarbeitung dieser Ereignisse erfordert unterschiedliche Logik, aber Sie möchten keine zwei unabhängigen Instanzen der Datenstromverarbeitung ausführen. Einige Benutzer sind möglicherweise nur an einer bestimmten Aktie interessiert und nur dann, wenn eine bestimmte externe Bedingung gilt – eine Bedingung, die möglicherweise nicht notwendigerweise Teil der Datenstromdaten ist (und daher eine dynamische Überprüfung zur Laufzeit als Teil der Verarbeitung benötigt).

Benutzer ändern ihre Interessen ständig, sodass ihre Abonnements für bestimmte Ereignisströme dynamisch kommen und gehen. So ändert sich die Streamingtopologie dynamisch und schnell. Darüber hinaus entwickelt sich die Verarbeitungslogik pro Benutzer dynamisch basierend auf Benutzerstatus und externen Ereignissen. Externe Ereignisse können die Verarbeitungslogik für einen bestimmten Benutzer ändern. Wenn beispielsweise eine neue Cheating-Methode entdeckt wird, muss die Verarbeitungslogik in einem Spiel-Cheating-Erkennungssystem mit der neuen Regel aktualisiert werden, um diese Verletzung zu erkennen. Dies muss natürlich erfolgen, ohne die laufende Verarbeitungspipeline zu unterbrechen. Massendatenstromverarbeitungsmodule wurden nicht entwickelt, um solche Szenarien zu unterstützen.

Es geht fast ohne Worte, dass ein solches System auf mehreren netzwerkgebundenen Computern ausgeführt werden muss, nicht nur auf einem einzigen Knoten. Daher muss die Verarbeitungslogik skalar und elastisch über einen Servercluster verteilt werden.

Neue Anforderungen

Es wurden vier grundlegende Anforderungen für ein Stream-Processing-System identifiziert, um die oben genannten Szenarien zu adressieren.

  1. Flexible Datenstromverarbeitungslogik
  2. Unterstützung für hoch dynamische Topologien
  3. Feinkornierte Datenstrom granularität
  4. Verteilung

Flexible Datenstromverarbeitungslogik

Das System sollte verschiedene Möglichkeiten zum Ausdrücken der Datenstromverarbeitungslogik unterstützen. Für vorhandene Systeme, die oben erwähnt wurden, müssen Entwickler ein deklaratives Datenflussberechnungsdiagramm schreiben, in der Regel nach einem funktionalen Programmierstil. Dies begrenzt die Ausdrucksfähigkeit und Flexibilität der Verarbeitungslogik. Orleans Datenströme sind gleichgültig, wie die Verarbeitungslogik ausgedrückt wird. Sie kann als Datenfluss (z. B. mit reaktiven Erweiterungen (Rx) in .NET), einem Funktionsprogramm, einer deklarativen Abfrage oder einer allgemeinen imperativen Logik ausgedrückt werden. Die Logik kann zustandsbehaftet oder zustandslos sein, kann möglicherweise Nebenwirkungen haben oder auch nicht, und kann externe Aktionen auslösen. Die gesamte Leistung geht an den Entwickler.

Unterstützung für dynamische Topologien

Das System sollte die dynamische Entwicklung von Topologien ermöglichen. Vorhandene oben genannte Systeme sind in der Regel auf statische Topologien beschränkt, die zur Bereitstellungszeit festgelegt wurden, die nicht zur Laufzeit weiterentwickelt werden können. Im folgenden Beispiel eines Datenflussausdrucks ist alles schön und einfach, bis Sie ihn ändern müssen:

Stream.GroupBy(x=> x.key).Extract(x=>x.field).Select(x=>x+2).AverageWindow(x, 5sec).Where(x=>x > 0.8) *

Ändern Sie die Schwellenwertbedingung im Where Filter, fügen Sie eine Select Anweisung hinzu, oder fügen Sie eine weitere Verzweigung im Datenflussdiagramm hinzu, und erstellen Sie einen neuen Ausgabedatenstrom. In vorhandenen Systemen ist dies nicht möglich, ohne die gesamte Topologie zu zerreißen und den Datenfluss von Grund auf neu zu starten. In der Praxis speichern diese Systeme die vorhandene Berechnung und können vom neuesten Checkpoint neu gestartet werden. Dennoch ist ein solcher Neustart störend und kostspielig für einen Onlinedienst, der Ergebnisse in Echtzeit erzeugt. Ein solcher Neustart wird besonders unpraktisch, wenn es um eine große Anzahl solcher Ausdrücke geht, die mit ähnlichen, aber unterschiedlichen Parametern (pro Benutzer, pro Gerät usw.) ausgeführt werden, die sich ständig ändern.

Das System sollte die Entwicklung des Datenstromverarbeitungsdiagramms zur Laufzeit ermöglichen, indem neue Verknüpfungen oder Knoten zum Berechnungsdiagramm hinzugefügt oder die Verarbeitungslogik innerhalb der Berechnungsknoten geändert wird.

Feinkornierte Datenstrom granularität

In vorhandenen Systemen ist die kleinste Abstraktionseinheit in der Regel der gesamte Fluss (Topologie). Viele Zielszenarien erfordern jedoch eine einzelne Knoten/Verknüpfung in der Topologie, um eine logische Entität selbst zu sein. Auf diese Weise kann jede Entität potenziell unabhängig verwaltet werden. In einer großen Datenstromtopologie, die mehrere Verknüpfungen umfasst, können unterschiedliche Verknüpfungen unterschiedliche Merkmale aufweisen und über verschiedene physische Transporte implementiert werden. Einige Links gehen möglicherweise über TCP-Sockets, während andere zuverlässige Warteschlangen verwenden. Unterschiedliche Links können unterschiedliche Liefergarantien haben. Verschiedene Knoten können unterschiedliche Prüfpunktstrategien haben, und ihre Verarbeitungslogik kann in verschiedenen Modellen oder sogar in unterschiedlichen Sprachen ausgedrückt werden. Diese Flexibilität ist in der Regel in bestehenden Systemen nicht möglich.

Der Vergleich der Einheit von Abstraktion und Flexibilität ähnelt dem Vergleich von SoA (Service Oriented Architectures) und Aktoren. Akteursysteme ermöglichen mehr Flexibilität, da jeder Akteur im Wesentlichen ein eigenständiger verwalteter "winziger Dienst" ist. Ebenso sollte das Datenstromsystem eine solche feinkörnige Kontrolle ermöglichen.

Verteilung

Und natürlich sollte das System alle Eigenschaften eines "guten verteilten Systems" haben. Dazu gehören:

  1. Skalierbarkeit: Unterstützt eine große Anzahl von Datenströmen und Computeelementen.
  2. Elastizität: Ermöglicht das Hinzufügen oder Entfernen von Ressourcen, um basierend auf der Last zu wachsen oder sich zu verkleinern.
  3. Zuverlässigkeit: Ausfallsicher.
  4. Effizienz: Nutzt zugrunde liegende Ressourcen effizient.
  5. Reaktionsfähigkeit: Ermöglicht Nahezu-Echtzeitszenarien.

Dies waren die Anforderungen für das Erstellen von Orleans Streaming.

Klarstellung: Orleans Derzeit wird das Schreiben deklarativer Datenflussausdrücke wie im obigen Beispiel nicht direkt unterstützt. Die aktuellen Orleans Streaming-APIs sind allgemeinere Bausteine, wie bei Orleans Streaming-APIs beschrieben.

Siehe auch

Orleans Stream-Programmierungs-APIs