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:

akka actor address and path
  • 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 distributed ActorSystem.
  • 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
_37
open System
_37
open Akka.Actor
_37
open Akka.Configuration
_37
open Akka.FSharp
_37
_37
let 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
_37
let system = System.create "RemoteFSharp" config
_37
let 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
_37
Console.ReadLine() |> ignore

In your terminal run RemoteActor.fsx to let the remote machine listen for messages


_10
dotnet 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
_33
open System
_33
open Akka.Actor
_33
open Akka.Configuration
_33
open Akka.FSharp
_33
_33
let 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
_33
let system = ActorSystem.Create("RemoteFSharp", configuration)
_33
let echoClient = system.ActorSelection("akka.tcp://[email protected]:9001/user/EchoServer")
_33
let task = echoClient <? "F#!"
_33
let response = Async.RunSynchronously (task, 1000)
_33
printfn "Reply from remote %s" (string(response))

Open up another terminal and run LocalActor.fsx to let the remote machine listen for messages


_10
dotnet fsi --langversion:preview LocalActor.fsx

You should be able to see the following on your terminal

Output

 Inside AmazonPasswords, 2FA, and Yubikeys 

Want more?

Subscribe to get my latest content via email. I won’t send you spam, and you can unsubscribe at any time.