My Journey on learning F#
September 19, 2020 • 3 min read • Also published at Notion. • Open • Code
Location transparency
Location transparency means that whenever you send a message to an actor, you don't need to know where they are within an actor system, which might span hundreds of computers. You just have to know that actors' address.
Actors work just the same way - in Akka.NET every actor has an address that contains the following parts:
- Protocol: Just like HTTP, HTTPS, FTP, etc, Akka.Net supports multiple protocol in order to send messages. If you're using remoting or clustering, you'll typically use a socket transport like akka.tcp:// or akka.udp:// to communicate between nodes
- ActorSystem - every
ActorSystem
instance in Akka.NET has to be given a name upon startup, and that name can be shared by multiple processes or machines that are all participating in a distributedActorSystem
. - Address - if you're not using remoting, then the address portion of an
ActorPath
can be omitted. But this is used to convey specific IP address / domain name and port information used for remote communication between actor systems. - Path - this is the path to a specific actor at an address. It's structure just like a URL path for a website, with all user-defined actors stemming off of the
/user/
root actor.
_37// RemoteActor.fsx_37#r "nuget: Akka.FSharp" _37#r "nuget: Akka.Remote"_37_37open System_37open Akka.Actor_37open Akka.Configuration_37open Akka.FSharp_37_37let config =_37 Configuration.parse_37 @"akka {_37 actor.provider = ""Akka.Remote.RemoteActorRefProvider, Akka.Remote""_37 remote.helios.tcp {_37 hostname = ""127.0.0.1""_37 port = 9001_37 }_37 }"_37_37let system = System.create "RemoteFSharp" config_37let echoServer = _37 spawn system "EchoServer"_37 <| fun mailbox ->_37 let rec loop() =_37 actor {_37 let! message = mailbox.Receive()_37 let sender = mailbox.Sender()_37 printfn "echoServer called"_37 match box message with_37 | :? string -> _37 sender <! sprintf "Echo: %s" message_37 return! loop()_37 | _ -> failwith "Unknown message"_37 }_37 loop()_37_37Console.ReadLine() |> ignore
In your terminal run RemoteActor.fsx
to let the remote machine listen for messages
_10dotnet fsi --langversion:preview RemoteActor.fsx
Now lets write some Local actor code
_33//LocalActor.fsx_33#r "nuget: Akka.FSharp" _33#r "nuget: Akka.Remote"_33_33open System_33open Akka.Actor_33open Akka.Configuration_33open Akka.FSharp_33_33let configuration = _33 ConfigurationFactory.ParseString(_33 @"akka {_33 actor {_33 provider = ""Akka.Remote.RemoteActorRefProvider, Akka.Remote""_33 deployment {_33 /remoteecho {_33 remote = ""akka.tcp://[email protected]:9001""_33 }_33 }_33 }_33 remote {_33 helios.tcp {_33 port = 0_33 hostname = ""127.0.0.1""_33 }_33 }_33 }")_33_33let system = ActorSystem.Create("RemoteFSharp", configuration)_33let echoClient = system.ActorSelection("akka.tcp://[email protected]:9001/user/EchoServer")_33let task = echoClient <? "F#!"_33let response = Async.RunSynchronously (task, 1000)_33printfn "Reply from remote %s" (string(response))
Open up another terminal and run LocalActor.fsx
to let the remote machine listen for messages
_10dotnet fsi --langversion:preview LocalActor.fsx
You should be able to see the following on your terminal