Startsidan  ▸  Texter  ▸  Teknikblogg

Anders Hesselbom

Programmerare, skeptiker, sekulärhumanist, antirasist.
Författare till bok om C64 och senbliven lantis.
Röstar pirat.

Introduktion till Akka .NET Remote

2015-05-13

Akka .NET Remote låter aktörerna i Akka .NET skicka meddelanden till andra processer genom Windows Sockets. Det innebär att ett system kan distribueras över flera processer oavsett om de ligger på samma fysiska maskin eller på en annan maskin i nätverket.

Arkitekturen i Akka .NET Remote är serverfri – varje peer kan kontakta och kommunicera med vilken annan peer som helst, givet att namn och port är känt. Det innebär att om du bygger en server, kan den utan problem förmedla direktkontakt mellan sina klienter.

Detta exempel visar ett mycket enkelt bokningssystem av en biosalong med tre stolar. Systemet består av tre stycken projekt, en server, ett datalager och en klient. Servern och klienten är Console Applications (C#) och datalagret är ett klassbibliotek.

vs

Servern
Låt oss börja med att titta på servern. I mitt exempel heter den BioServer. All kod som visas i servern förutsätter följande:

1. Akka .NET är installerat. Detta kan göras med följande Nuget-kommando:

Install-Package Akka

2. Akka .NET Remote är installerat.

Install-Package Akka.Remote

3. Följande using-sats:

using Akka.Actor;

Så här ser huvudprogrammet ut:

class Program
{
   public static Stollista stolar;

   static void Main(string[] args)
   {
      var config =
         Akka.Configuration.ConfigurationFactory.ParseString(@"
akka {
    actor {
        provider = ""Akka.Remote.RemoteActorRefProvider, Akka.Remote""
    }

    remote {
        helios.tcp {
            port = 8080
            hostname = localhost
        }
    }
}
");

      stolar = new Stollista()
         { new Stol(1), new Stol(2), new Stol(3) };
      Console.WriteLine(stolar.ToString());

      using (var system =
         Akka.Actor.ActorSystem.Create("AllaBokare", config))
      {
         var bokare = system.ActorOf(new
            Akka.Actor.Props(typeof(Bokningsaktor)),"Bokare");
         Console.ReadLine();
      }
   }
}

Notera att konfigurationen anger vilken port servern ska lyssna på (8080). Den kodraden har jag klippt ut från dokumentationen för Akka .NET Remote och klistrat in här. Portnumret måste vara förutbestämt för att den första klienten ska kunna hitta servern.

Därefter har jag min biosalong bestående av tre stolar. Dessa beskrivs av följande klasser:

class Stollista : List<Stol>
{
   public override string ToString()
   {
      var ret = new System.Text.StringBuilder();
      foreach (var s in this)
         ret.AppendLine(s.ToString());
      return ret.ToString();
   }

   public bool Boka(int stolNr, int bokadAv)
   {
      var stol = this.Find(m => m.StolNr == stolNr);
      if (stol == null)
         return false;
      stol.BokadAv = bokadAv;
      return true;
   }
}

Därefter använder jag Akka.Actor.ActorSystem.Create för att skapa mitt aktörssystem (kallad AllaBokare) på samma sätt som om jag hade tänkt att använda Akka .NET i en och samma process, och i using-blocket för aktörssystemet så skapar jag min aktör (kallad Bokare). Det som återstår i servern är klassen som beskriver aktören. Den ser ut så här:

class Bokningsaktor : Akka.Actor.ReceiveActor
{

   public Bokningsaktor()
   {
      this.Receive(b => {
         Console.WriteLine("Ny bokning!");
         Program.stolar.Boka(b.StolNr, b.BokadAv);
         Console.WriteLine(Program.stolar.ToString());
      });
   }
}

Datalagret
Datalagret har jag valt att lägga i ett annat projekt i samma lösning som servern. Jag har kallat datalagret för BioData. Här finns en klass som beskriver meddelandet som klienten kan skicka till servern.

public class Bokningsmeddelande
{
   public int StolNr { get; private set; }
   public int BokadAv { get; private set; }
   public Bokningsmeddelande(int stolNr, int bokadAv)
   {
      this.StolNr = stolNr;
      this.BokadAv = bokadAv;
   }

   public override string ToString()
   {
      return string.Format("Bokning från {0} på stol {1}.",
         this.BokadAv, this.StolNr);
   }
}

Både servern och klienten ska ha en referens till datalagret.

Klienten
Klienten är mycket enkel. Notera först skillnaden i konfigurationen mellan klienten och servern. Servern har port 8080, vilket klienten måste veta om för att kunna hitta servern. Men när klienten gjort sig tillkänna så vet servern vilken port klienten använder, därför behöver vi inte bestämma någon port åt klienten. Att ange port 0 är att begära dynamisk port.

Därefter skapar vi ett aktörssystem med det godtyckliga namnet Bokningsklient. Från systemet i klienten väljer vi att ansluta oss till servern genom att anropa ActorSelection. Som argument använder jag sökvägen till aktören på servern (som hette Bokare i systemet AllaBokare). Slutligen samlar jag in information från slutanvändaren som skickas till servern med metoden Tell. Så här ser källkoden för klienten ut:

class Program
{
   static void Main(string[] args)
   {
      var config = Akka.Configuration.ConfigurationFactory.ParseString(@"
akka {
    actor {
        provider = ""Akka.Remote.RemoteActorRefProvider, Akka.Remote""
    }
    remote {
        helios.tcp {
            port = 0
            hostname = localhost
        }
    }
}
");

      using (var system =
         Akka.Actor.ActorSystem.Create("Bokningsklient", config))
      {
         var bokare = system.ActorSelection(
            "akka.tcp://AllaBokare@localhost:8080/user/Bokare");
         Console.Write("Vad är ditt användar-ID? Skriv ett heltal. ");
         var userId = int.Parse(Console.ReadLine());
         while(true)
         {
            Console.Write("Vilken stol vill du boka? (1-3) ");
            var stol = Console.ReadLine();
            if (stol == "")
               break;
            bokare.Tell(new
               BioData.Bokningsmeddelande(int.Parse(stol), userId));
         }
         system.Shutdown();
      }
   }
}

Bilden visar servern bakom en klient.

akka_remote

Eftersom portnumret tilldelas till klienten dynamiskt så kan flera klienter startas och boka platser. Och eftersom arkitekturen i Akka .NET Remote är peer-to-peer så kan dessa skicka meddelanden till varandra.

Categories: C#

Tags: Akka .NET

Leave a Reply

Your email address will not be published. Required fields are marked *



En kopp kaffe!

Bjud mig på en kopp kaffe (20:-) som tack för bra innehåll!

Bjud på en kopp kaffe!

Om...

Kontaktuppgifter, med mera, finns här.

Följ mig

Twitter Instagram
GitHub RSS

Public Service

Folkbildning om public service.

Hem   |   linktr.ee/hesselbom   |   winsoft.se   |   80tal.se   |   Filmtips