Freitag, 4. Dezember 2015

Akka.NET Adventskalender – Tür 4

Verschiedene Aktor Typen

Gestern haben wir unseren ersten Aktor erzeugt und ihn von der Klasse UntypedActor abgeleitet. Es gibt aber noch mehr Basisklassen, die für die Erzeugung von Aktoren in Frage kommen. Heute werden wir uns die drei wichtigsten und grundlegendsten ansehen.

Der einfachste

Der UntypedActor, den wir gestern kennengelernt haben, ist der einfachste Typ von Aktor, den Du erstellen kannst. Letztlich ist es Geschmacksfrage, welcher Typ von Aktor von Dir als Basis verwendet wird. Also zeige ich Dir die drei wichtigsten und Du kannst dann von Fall zu Fall entscheiden, welcher Dir für welchen Zweck am besten gefällt.

Beim UntypedActor musst Du lediglich eine Methode bereit stellen, die sämtliche Nachrichten erhält, die an den Aktor gesandt werden.

protected override void OnReceive(object message)
{
    // handle all messages received
}

Du entscheidest, ob Du eine Nachricht annimmst und was Du mit ihr anfängst. Typischerweise wird eine mehr oder weniger lange if-else Kaskade innerhalb dieser Methode stehen. Allerdings kann dieser Aktor bereits verschiedene Verhalten bekommen. Mehr dazu gleich.

Etwas mehr C# bitte

Vermutlich war Dir das obige Beispiel zu wenig an die Fähigkeiten – insbesondere die Typsicherheit von C# angelehnt. Wenn Du einen typsicheren Aktor haben möchtest (dieser kann dann jedoch keine Verhalten bekommen) dann kannst Du Deinen Aktor von TypedActor ableiten. Dieser wird zuätzlich mit jeder Menge IHandle<> Interface Deklarationen verziert und erhält dem Interface entsprechend eine Menge Handle() Methoden, die sich jeweils um die Bearbeitung eines Typs von Nachricht kümmern. Unser HelloWorld-Aktor sähe dann so aus:

using System;
using Akka.Actor;

namespace AkkaHelloWorld
{
    public class HelloTyped : TypedActor, IHandle<string>
    {
        public void Handle(string message)
        {
            Console.WriteLine("Received: '{0}'", message);
        }
    }
}

Auf den ersten Blick sehen solche Aktoren sehr vernünftig aus, vor Allem wenn man Typsicherheit im Hinterkopf hat. Jedoch können solche Aktoren kein Verhalten bekommen, da das verschiedene Reaktionen auf gleiche Nachrichten-Typen erfordert.

Und noch einer

Mein persönlicher Favorit (nein, nein beeinflussen will ich Dich hiermit nicht) ist der ReceiveActor. Es ist eine Mixtur aus Typsicherheit und Flexibilität. Und das häufig gepriesene Verhalten kann er auch. Aber schauen wir uns erst einmal an, wie unser einfacher Hello-Aktor aussehen würde:

using System;
using Akka.Actor;

namespace AkkaHelloWorld
{
    public class HelloReceive : ReceiveActor
    {
        public HelloReceive()
        {
            Receive<string>(s => HandleStringMessage(s));
        }

        public void HandleStringMessage(string message)
        {
            Console.WriteLine("Received: '{0}'", message);
        }
    }
}


Mit diesem Wissen ausgestattet kannst Du künftig entscheiden, wie Du Deine Aktoren baust.

Wie war das jetzt mit dem Verhalten?

Wenn wir an uns Menschen denken, so sind wir durchaus in unterschiedlicher Verfassung. Manchmal sind wir ärgerlich, manchmal freundlich oder unterscheiden zwischen anderen Gemütszuständen. Je nach unserem Zustand reagieren wir auf gleiche Ereignisse möglicherweise unterschiedlich. Genau das ist es, wenn wir bei einem Aktor von Verhalten (behavior) sprechen.  Typischerweise nutzt man die Verhalten, um einen Zustandsautomaten zu modellieren.
Um zu verstehen, was ich meine, bauen wir uns einen einfachen Aktor, der zwischen Wahrheit erzählen und Lügen hin- und herschaltet. Wir fragen ihn nach der Zeit und erhalten gelegentlich eine wahre und gelegentlich eine gelogene Antwort.

using System;
using Akka.Actor;

namespace AkkaHelloWorld
{
    public class TimeReader : ReceiveActor
    {
        private Random random;

        public TimeReader()
        {
            random = new Random();

            Become(TruthTelling);
        }

        #region behaviors
        private void TruthTelling()
        {
            Receive<string>(s => TellCorrectTime(s));
        }

        private void Lying()
        {
            Receive<string>(s => TellAnyTime(s));
        }
        #endregion

        #region message handlers
        private void TellCorrectTime(string _)
        {
            Console.WriteLine("Current time is: {0:hh:mm}-really",
                DateTime.Now
            );
            if (random.Next(100) < 50)
                Become(Lying);
        }

        private void TellAnyTime(string _)
        {
            Console.WriteLine("Current time is: 11:92-do you believe it?");
            Become(TruthTelling);
        }
        #endregion
    }
}


Ein mögliches Resultat könnte so aussehen:

Current time is: 10:26-really
Current time is: 11:92-do you believe it?
Current time is: 10:26-really
Current time is: 11:92-do you believe it?
Current time is: 10:26-really
Current time is: 10:26-really

Wenn Du in der Akka.NET Dokumentation zu diesem Thema nachschlägst, wirst Du noch weitere Informationen erhalten. Zum Beispiel auch zum "stashing", also dem Aufschieben von Nachrichten bis ein Aktor wieder im richtigen Zustand ist.

Aktoren können aber noch viel mehr – das sehen wir uns morgen an.

Donnerstag, 3. Dezember 2015

Akka.NET Adventskalender – Tür 3

Hallo Aktor

Jetzt wo wir über die notwendigen Grundlagen verfügen, können wir unsere erste Anwendung schreiben und unseren ersten Aktor einsetzen. Starte Deine Entwicklungs-Umgebung und erzeuge ein neues Konsolen-Projekt. Alle Beispiele, die wir bis Weihnachten erstellen, werden Kommandozeilen Anwendungen sein. Der Hauptgrund dahinter ist, dass so plattformbedingte Unterschiede, die es bei GUI Anwendungen gäbe, dann nicht auftreten.
Leider habe ich heute keinen Link auf ein github-Projekt, aber Du wirst sehen, wie wenig wir selbst schreiben müssen.

So, nun wo das Projekt da ist, füge "Akka" zur Liste er NuGet Pakete hinzu. Nun sollte sich diese Klasse compilieren lassen:

using System;
using Akka.Actor;

namespace AkkaHelloWorld
{
    public class MainClass
    {
        public static void Main(string[] args)
        {
            var system = ActorSystem.Create("World");

            // TODO: do something with actor system

            Console.WriteLine("Press [enter] to continue");
            Console.ReadLine();

            system.Shutdown();
            system.AwaitTermination();
        }
    }
}

Was passiert hier?

Leider noch nicht viel, aber wir sehen den typischen Aufbau einer Akka.NET Anwendung. Wir erzeugen ein ActorSystem, geben ihm einen Namen, tun etwas mit diesem System (was noch vor uns liegt) und beenden das System wieder kontrolliert. Damit unser System genug Gelegenheit hat, zu arbeiten, warten wir auf eine Zeilen-Eingabe, damit es sich nicht unverrichteter Dinge wieder beendet.

Zeit unseren ersten Aktor zu schreiben. Leg' einfach eine Klasse "Hello" im gleichen Namensraum an, in dem auch die Konsolen-Applikation liegt. Das sollte für den Moment reichen. Was die Benennung von Aktoren-Klassen angeht, so sieht man auch häufig Namen, die das Wort "Actor" als Anhang tragen und damit mehr den in der .NET Welt üblichen Konventionen entsprechen. In dieser Artikel-Serie verwende ich diese Konvention nicht, es spricht aber nichts dagegen, dass Du es in Deinen Projekten machst. Entscheide solche Dinge einfach mit Deinem Team.

using System;
using Akka.Actor;

namespace AkkaHelloWorld
{
    public class Hello : UntypedActor
    {
        protected override void OnReceive(object message)
        {
            Console.WriteLine("Received: '{0}'", message);
        }
    }
}

Was macht dieser Aktor?

Zunächst bitte ich Dich, die Basisklasse (UntypedActor) zu ignorieren. Wir werden uns mit ein paar Basisklassen für Aktoren morgen intensiver befassen. Für heute genügt zunächst zu wissen, dass die Basisklasse UntypedActor eine Methode OnReceive() erwartet, die für die Behandlung aller eintreffenden Nachrichten verantwortlich ist. Behalte dabei bitte im Kopf, dass die Mailbox ein FIFO Speicher ist und Nachrichten einzeln bearbeitet werden, niemals parallel!

Wie senden wir nun Nachrichten?

Das siehst Du sofort, es ist ganz einfach. Ersetze in der Konsolen Anwendung einfach den mit TODO markierten Kommentar durch diese zwei Zeilen:

var hello = system.ActorOf<Hello>();
hello.Tell("Hello World");

Wenn Du nun Dein Programm startest, solltest Du diese Ausgabe auf deinem Terminal-Fenster erhalten:

Received: 'Hello World'
Press [enter] to continue

Wunderbar! Dein erster Aktor hat seine erste Nachricht (einen String) erhalten.

Was genau ist hier passiert?

Sieht eigentlich ganz einfach aus, macht aber einen recht umständlichen Eindruck. Aktoren sind ja nicht einfach nur Klassen, die instantiiert werden wie Objekte, sondern werden durch eine Laufzeitumgebung gesteuert, müssen be Bedarf neu gestartet werden und laufen möglicherweise auf einem anderen Rechner. Insofern ist die Konstruktion ein wenig aufwändiger, als der reine Konstruktor-Aufruf.

Zur Erzeugung eines Aktors kann ein Objekt des Typs Props verwendet werden. Die nachfolgenden Zeilen zeigen die grundsätzlichen Alternativen, die sich bei der Benutzung von Props bieten. Zusätzlich können dem eigentlichen Konstruktur noch weitere Parameter mitgegeben werden – übergebe sie einfach der Create Methode mit. Und auch die ActorOf() Methode kann wietere Parameter z.B. einen Namen bekommen. Wird kein Name angegeben, so vergibt Akka.NET einen innerhalb dieser Hierarchie eindeutigen.

var hello = system.ActorOf<Hello>();
var hello = system.ActorOf(Props.Create<Hello>());
var hello = system.ActorOf(Props.Create(typeof(Hello));
var hello = system.ActorOf(Props.Create(() => new Hello()));

Alle Erzeugungs-Methoden liefern eine ActorRef. Das ist der vorher erwähnte Proxy, der sich wie ein Aktor verhält und den genauen Aufenthaltsort des Aktors kennt. Wir müssen uns darum nicht kümmern.

Mittels des ActorRef Objekts können wir über die Methode Tell() Nachrichten an den Aktor senden. Technisch gesehen ist eine Nachricht ein beliebiges CLR Objekt – es muss nur serialisierbar sein. Einfache Wert-Datentypen wie double oder int funktionieren ebenso problemlos wie aus Klassen instantiierte Objekte oder string Literale. Wir werden uns aber noch eingehender mit Nachrichten befassen.

Bitte hebe die heutigen Projekt-Dateien auf, wir werden morgen weiter darauf aufbauen.

Mittwoch, 2. Dezember 2015

Akka.NET Adventskalender – Tür 2

Was ist eigentlich ein Aktor?

So langsam wird es Zeit, dass wir herausfinden, was eigentlich ein Aktor ist. Man kann einen Aktor mit einem Objekt aus der Objektorientierung vergleichen.

  • Ein Aktor speichert einen Zustand (in Form von Feldern und Eigenschaften eines CLR Objektes, das wir bequem in C# anlegen). Der Zustand ist für die Außenwelt gar nicht sichtbar. Das ist wichtig, denn das Aktor Modell versucht, den gefürchteten verteilten Zustand (shared state) mit all seinen Problemen (Locking, Deadlocks, inkonsistente Zustände, etc.) dadurch gar nicht erst aufkommen zu lassen. Nur der Aktor selbst hat Zugriff auf seinen Zustand!
  • Jeder Aktor empfängt Nachrichten, die an ihn gesandt werden und führt Aktionen als Folge davon aus. Alle eintreffenden Nachrichten werden in einer als FIFO organisierten Mailbox gespeichert und nacheinander abgearbeitet. Akka.NET sorgt dafür, dass jeder Aktor immer nur eine Nachricht zu jedem Zeitpunkt verarbeitet. Das bedeutet dann leider auch, dass wir typischerweise keine weiteren parallelen Aktionen (z.B. in Form von Tasks) innerhalb eines Aktors ausführen. Das ist einzig die Aufgabe der Laufzeit-Umgebung von Akka.NET.
  • Ein Aktor kann wahlweise verschiedene Verhalten annehmen. So wie wir Menschen mal gut oder schlecht gelaunt sind, kann ein Aktor Zustände (im Sinne eines Zustandsautomaten) annehmen. Technisch gesehen reagiert der Aktor je nach Zustand anders auf Nachrichten, die ihm zugestellt werden.
  • Aktoren dürfen Kind-Aktoren erzeugen, kontrollieren und wieder beenden. Kind-Aktoren und deren korrekte Beaufsichtigung sind der Schlüssel für belastbare Systeme. Wie im täglichen leben: Eltern haften für ihre Kinder. Typischerweise baut man damit hierarchisch gestaltete Verantwortungs-Bäume auf, die von oben nach unten Aufgaben und vielleicht auch Verantwortung deligieren. Je weiter oben die Aktoren stehen, desto mehr Verantwortung und weniger eigenes Risiko besitzen die Aktoren. Die Aktoren am Ende des Baums führen nur noch einfache Aufgaben aus, müssen aber enventuell riskante Tätigkeiten ausführen, die tödlich enden können.

Wo leben die Aktoren?

Aktoren leben in Aktor Systemen. Ein Rechner kann beliebig viele Aktor Systeme beherbergen. Die einzelnen Systeme sind aber zunächst voneinander unabhängig, können aber durchaus miteinander arbeiten. Durch entsprechende Konfiguration gesteuert können Aktoren auch auf anderen Systemen erzeugt werden (location transparent) und dort ihre Arbeit verrichten. Als Entwickler spürt man zunächst keinen Unterschied. Um das zu ermöglichen, werden wir sogenannte Aktor-Referenzen (ActorRef) kennenlernen, die sich wie ein Stellvertreter (Proxy) zum tatsächlichen Aktor Verhalten. Wir sprechen niemals mit dem Aktor direkt sondern immer über die Referenz. Der einzige Unterschied, der möglicherweise auftreten kann, sind Fehler, die z.B. durch Netzwerk-Probleme verursacht werden. Dafür muss man entsprechende Vorkehrungen treffen. Alle Beispiele, die wir in den folgenden Tagen bearbeiten werden, laufen allerdings immer auf dem lokalen Rechner.

Morgen werden wir unseren ersten Aktor erstellen.

Dienstag, 1. Dezember 2015

Akka.NET Adventskalender – Tür 1

Worum geht es?

An den nächsten 24 Tagen (heute mitgezählt) kannst Du täglich einen Artikel über Akka.NET hier lesen. Falls Du Dich fragst, was dahinter steckt und wozu man Akka.NET benutzen kann, dann könnte diese Serie für Dich interessant sein. Dich erwarten ein paar Grundlagen, diverse Muster und viele Code Beispiele, die hoffentlich zum Verständnis beitragen. Wenn ich es schaffe, Dein Interesse bis zum Schluss zu behalten und Du selbst mit Akka.NET programmierst, dann habe ich mein Ziel erreicht.

Warum also Akka.NET einsetzen?

Akka.NET baut auf dem Aktor Modell auf (Alternative Beschreibung), das eine sehr elegante Lösung für die diversen Probleme bietet, die sich bei nebenläufigen, parallelen oder verteilten Systemen ergeben. Die zum Teil sehr umfangreichen Grundlagen möchte ich mir an dieser Stelle ersparen, aber wir alle haben vermutlich schon diverse Erfahrungen mit Threads, Prozessen und verteilten Systemen gemacht und so mache Lektion schmerzhaft erfahren müssen. Hinzu kommt leider die Tatsache, dass moderne CPUs unserer Rechner nicht mehr mit zunehmenden Taktfrequenzen aufwarten, sondern eher die Anzahl der Kerne, die zur Ausführung unserer Programme bereitstehen, zunehmen. Während wir vor 10 Jahren typischerweise einen Kern hatten, sind heute selbst in mobilen Computern 8 Kerne denkbar. Insofern müssen wir uns mit Parallel-Programmierung anfreunden, wenn wir unsere Hardware möglichst gut ausnutzen möchten.

Setzt man Werkzeuge wie Akka.NET ein, dann hält sich der Aufwand in puncto "Lernkurve" in Grenzen, sofern man mit Grundlagen der Objektorientierten Programmierung vertraut ist. Erste Ergebnisse sind sehr schnell sichtbar, große Dinge im Rahmen des Machbaren und Skalierung innerhalb einer Maschine (scale-in) ode die Skalierung auf zusätzliche Maschinen (scale-out) aus Sicht des Anwendungs-Entwicklers fast ohne Unterschied.

Wird das Aktor Modell überleben?

Gute Frage. Leider ist meine Glaskugel heute etwas trüb...  Was meiner Meinung nach großes Vertrauen schafft, ist die Tatsache, dass viele Leute auf dieses Modell setzen. Damit kann man zumindest heute diese Technologie als zukunftsträchtig einstufen. Programmiersprachen wie Erlang oder Elixir und viele andere mehr bieten native Unterstützung für Aktoren. So gut wie jede Plattform besitzt zahlreiche Implementierungen davon, meist mehr oder weniger an das in Scala geschriebene Akka angelehnt. Und in der .NET Welt gibt es zwei sehr prominente Kandidaten. Akka.NET ist vom Einstieg her relativ leicht beherrschbar und Microsoft bietet mit Orleans eine interessante quelloffene Alternative sowie mit Service Fabric die kommerzielle Variante, die innerhalb Azure bereits seit Jahren Verwendung findet. Grund genug also, sich mit dem Thema auseinander zu setzen.

Wir sind Reaktiv!

Reaktiv zu programmieren ist vermutlich inzwischen zu einem Modewort geworden. Aber wenn wir Akka.NET einsetzen, dann betreten wir die Welt der reaktiven Programmierung. Dahinter steckt ein Paradigma, welches durch das Reactive Manifesto beschrieben ist. Reaktive Systeme sind (Kurzform)

  • Responsiv und beantworten Anfragen innerhalb gegebener Zeit. Dahinter steckt vor allem der Gedanke, Probleme frühzeitig zu erkennen und geeignet zu reagieren.
  • Belastbar und reagieren selbst unter Last noch vernünftig.
  • Elastisch durch Hinzu- oder Wegnahme bestimmter Resourcen
  • Nachrichtengesteuert. Aktoren senden sich Nachrichten, um sich gegenseitig über bestimmte Zustände oder Ereignisse zu informieren oder Dinge abzufragen bzw. auszulösen.

Was erwartet Dich an den nächsten Tagen?

Die nachfolgenden Artikel sind eine Mixtur aus etwas Theorie, ein paar Grundlagen sowie Entwurfsmuster, die das Leben eines Reaktiven Entwicklers leichter machen. Der Schwerpunkt liegt auf praktischen Experimenten. Wir werden gemeinsam an Beispielen allgemeine Problemstellungen der Reaktiven Programmierung erarbeiten. Allerdings werde ich in dieser Artikel-Serie nicht immer sehr weit in die Details eintauchen. Es gibt ein wunderbares Tutorial, mit dem ich nicht konkurrieren kann und das ich auch nicht kopieren möchte. Du kannst es gerne gleichzeitig zu diesen Artikeln oder einfach anschließend absolvieren – es lohnt sich auf jeden Fall!

Die nachfolgenden Artikel sind als 4 Sprints organisiert, die jeweils an einem Sonntag (bzw. Heilig Abend) enden. Jeder Sprint steht unter jeweils einem eigenen Motto und behandelt die dazu passenden Grundlagen und Muster. Wir werden mit dem Beschnuppern von Akka.NET beginnen, uns dann den Einsatz einzelner Aktoren sowie Mengen an Aktoren ansehen und zum Schluss mit Publish/Subscribe Experimente anstellen.

Was muss ich vorbereiten?

Alle Code Beispiele sind in C# geschrieben (F# wäre auch möglich, mir fehlt jedoch das Know-how dazu). Du brauchst passende Entwicklungswerkzeuge. Je nach Deiner präferierten Plattform kannst Du mit MonoDevelop oder Visual Studio alle Beispiele nachvollziehen. Für größere Beispiele werden rechtzeitig git Repositories bereit gestellt sein.

Also – wenn ich Dich nicht abgeschreckt habe – bereite Deinen Rechner vor und morgen geht es los!

Mittwoch, 4. November 2015

Bald kommt Advent

Derzeit befasse ich mich sehr intensiv mit Akka.NET -- dem .NET Port des Akka Projekts, welches in Scala geschrieben ist und auf der JVM läuft.

Vom 1.12. bis zum 24.12. einschließlich wird es täglich einen neuen Artikel geben. Jede Woche steht unter einem neuen Motto, wir werden viele Entwurfsmuster besprechen und reichlich Code produzieren.

Alle Beispiele sind in C# programmiert und sind sowohl unter Windows als auch mit Mono realisierbar.

Wenn es euch interessiert, seid ab 1. Dezember dabei!