Search code examples
f#akka.netakka-remote-actorakka-remoting

Akka.NET: Dead Letters to Remote Actor


I am learning how to call a remote actor from a different machine. To simulate two different machines I have a Host machine and the other one is a Virtual Machine (VM). The Network Adapter is set to NAT because with this setting I am able to ping the host machine from VM (I read that it should be set to Bridge but the ping command timed out).

Host IP: 172.16.104.242
VM IP: 10.0.2.15

That aside, this is the code for RemoteActor.fsx on host machine

#r "nuget: Akka.FSharp" 
#r "nuget: Akka.Remote"

open System
open Akka.Actor
open Akka.Configuration
open Akka.FSharp

let config =
    Configuration.parse
        @"akka {
            actor.provider = ""Akka.Remote.RemoteActorRefProvider, Akka.Remote""
            remote.helios.tcp {
                hostname = 172.16.104.242
                port = 9001
            }
        }"

let system = System.create "RemoteFSharp" config
let echoServer = 
    spawn system "EchoServer"
    <| fun mailbox ->
        let rec loop() =
            actor {
                let! message = mailbox.Receive()
                let sender = mailbox.Sender()
                printfn "echoServer called"
                match box message with
                | :? string -> 
                    sender <! sprintf "Echo: %s" message
                    return! loop()
                | _ ->  failwith "Unknown message"
            }
        loop()

I first executed this script and this is the output enter image description here

This is the code for LocalActor.fsx on VM

#r "nuget: Akka.FSharp" 
#r "nuget: Akka.Remote"

open System
open Akka.Actor
open Akka.Configuration
open Akka.FSharp

let configuration = 
    ConfigurationFactory.ParseString(
        @"akka {
            actor {
                provider = ""Akka.Remote.RemoteActorRefProvider, Akka.Remote""
                deployment {
                    /remoteecho {
                        remote = ""akka.tcp://[email protected]:9001""
                    }
                }
            }
            remote {
                helios.tcp {
                    port = 0
                    hostname = 10.0.2.15
                }
            }
        }")

let system = ActorSystem.Create("RemoteFSharp", configuration)
let echoClient = system.ActorSelection("akka.tcp://[email protected]:9001/EchoServer")
let task = echoClient <? "F#!"
let response = Async.RunSynchronously (task, 1000)
printfn "Reply from remote %s" (string(response))

This is the output for this Local Remote

Now the RemoteActor.fsx throws this error Error

I found a few posts on Stack Overflow that had this same error but couldn't figure out the fix. Apparently the error is because the RemoteActor dies before the Local Actor sends the message. Also after running the RemoteActor.fsx script if I type this echoServer <! "Hello" in the RemoteActor terminal, I get the same error.

Any idea how to fix this? Any help would be greatly appreciated! Thank you!


Solution

  • Change this line

    let echoClient = system.ActorSelection("akka.tcp://[email protected]:9001/EchoServer")
    

    To

    let echoClient = system.ActorSelection("akka.tcp://[email protected]:9001/user/EchoServer")
    

    All user-defined actors exist under the /user actor root.