我如何解决:Akka.Remote.EndpointDisassociatedException?

时间:2017-03-24 15:11:30

标签: f# akka.net akka.net-cluster

我有some code涉及将actor部署到一个单独的进程上。

我得到:Akka.Remote.EndpointDisassociatedException

  

[警告] [3/24/2017 1:54:32 PM] [线程   0008] [[阿卡://系统1 /系统/ endpointMana   GER / reliableEndpointWriter-akka.tcp%3A%2F%2Fsystem2%40localhost%3A8080-1#1408457   663]]与远程系统的关联akka.tcp:// system2 @ localhost:8080   失败了;地址现在被门控5000毫秒。原因是:   [Akka.Remote.EndpointDisassociat edException:Disassociated at   Akka.Remote.EndpointWriter.PublishAndThrow(异常原因,LogLevel   leve l,Boolean needToThrow)at   Akka.Actor.ReceiveActor.ExecutePartialMessageHandler(对象消息,   Parti alAction 1 partialAction) at Akka.Actor.ActorCell.<>c__DisplayClass114_0.<Akka.Actor.IUntypedActorConte xt.Become>b__0(Object m) at Akka.Actor.ActorBase.AroundReceive(Receive receive, Object message)
at Akka.Actor.ActorCell.ReceiveMessage(Object message) at Akka.Actor.ActorCell.AutoReceiveMessage(Envelope envelope) at Akka.Actor.ActorCell.Invoke(Envelope envelope)] [ERROR][3/24/2017 1:54:32 PM][Thread 0008][akka://system1/system/endpointManager /reliableEndpointWriter-akka.tcp%3A%2F%2Fsystem2%40localhost%3A8080-1/endpointWr iter] Disassociated Cause: Akka.Remote.EndpointDisassociatedException: Disassociated at Akka.Remote.EndpointWriter.PublishAndThrow(Exception reason, LogLevel leve l, Boolean needToThrow) at Akka.Actor.ReceiveActor.ExecutePartialMessageHandler(Object message, Parti alAction
1 partialAction)at   Akka.Actor.ActorCell。&lt;&gt; c__DisplayClass114_0.b__0(对象m)at   Akka.Actor.ActorBase.AroundReceive(接收接收,对象消息)
  at Akka.Actor.ActorCell.ReceiveMessage(Object message)at   Akka.Actor.ActorCell.AutoReceiveMessage(信封信封)at   Akka.Actor.ActorCell.Invoke(信封信封)

这是我在一个触发该错误的单独进程中执行的代码:

use system = ActorSystem.Create("system1", config)
let reply = system.ActorOf<ReplyActor>("reply")

let props1 = Props.Create(typeof<SomeActor>, [||])
let props2 = Props.Create(typeof<SomeActor>, [||])
let props3 = Props.Create(typeof<SomeActor>, [||])

let remote1 = system.ActorOf(props1.WithRouter(FromConfig.Instance), "remoteactor1")
let remote2 = system.ActorOf(props2.WithRouter(FromConfig.Instance), "remoteactor2")
let remote3 = system.ActorOf(props3.WithRouter(FromConfig.Instance), "remoteactor3")

let hashGroup = system.ActorOf(Props.Empty.WithRouter(ConsistentHashingGroup(config)))
Task.Delay(500).Wait();

let routee1 = Routee.FromActorRef(remote1);
hashGroup.Tell(new AddRoutee(routee1));

let routee2 = Routee.FromActorRef(remote2);
hashGroup.Tell(new AddRoutee(routee2));

let routee3 = Routee.FromActorRef(remote3);
hashGroup.Tell(new AddRoutee(routee3));

Task.Delay(500).Wait();

for i = 0 to 5 do
    for j = 0 to 7 do

        let message = new HashMessage(j, sprintf "remote message: %i" j);
        hashGroup.Tell(message, reply);

Console.ReadLine() |> ignore

以下是我的远程部署代码所依赖的配置:

open Akka.Configuration

let config = ConfigurationFactory.ParseString(@"
    akka {  
        log-config-on-start = on
        stdout-loglevel = DEBUG
        loglevel = DEBUG
        actor {
            provider = ""Akka.Remote.RemoteActorRefProvider, Akka.Remote""

            debug {  
              receive = on 
              autoreceive = on
              lifecycle = on
              event-stream = on
              unhandled = on
            }

            deployment {
                /localactor {
                    router = consistent-hashing-pool
                    nr-of-instances = 5
                    virtual-nodes-factor = 10
                }
                /remoteactor1 {
                    router = consistent-hashing-pool
                    nr-of-instances = 5
                    remote = ""akka.tcp://system2@localhost:8080""
                }
                /remoteactor2 {
                    router = consistent-hashing-pool
                    nr-of-instances = 5
                    remote = ""akka.tcp://system2@localhost:8080""
                }
                /remoteactor3 {
                    router = consistent-hashing-pool
                    nr-of-instances = 5
                    remote = ""akka.tcp://system2@localhost:8080""
                }
            }
        }
        remote {
            helios.tcp {
                port = 8090
                hostname = localhost
            }
        }
    }
    ")

以下是我的F#实施所依据的实际有效的C#代码:

var config = ConfigurationFactory.ParseString(@"
akka {  
    log-config-on-start = on
    stdout-loglevel = DEBUG
    loglevel = DEBUG
    actor {
        provider = ""Akka.Remote.RemoteActorRefProvider, Akka.Remote""

        debug {  
          receive = on 
          autoreceive = on
          lifecycle = on
          event-stream = on
          unhandled = on
        }

        deployment {
            /localactor {
                router = consistent-hashing-pool
                nr-of-instances = 5
                virtual-nodes-factor = 10
            }
            /remoteactor1 {
                router = consistent-hashing-pool
                nr-of-instances = 5
                remote = ""akka.tcp://system2@localhost:8080""
            }
            /remoteactor2 {
                router = consistent-hashing-pool
                nr-of-instances = 5
                remote = ""akka.tcp://system2@localhost:8080""
            }
            /remoteactor3 {
                router = consistent-hashing-pool
                nr-of-instances = 5
                remote = ""akka.tcp://system2@localhost:8080""
            }
        }
    }
    remote {
        dot-netty.tcp {
            port = 8090
            hostname = localhost
        }
    }
}
");
            using (var system = ActorSystem.Create("system1", config))
            {
                var reply = system.ActorOf<ReplyActor>("reply");

                //create a remote deployed actor
                var remote1 = system.ActorOf(Props.Create(() => new SomeActor(null, 123)).WithRouter(FromConfig.Instance), "remoteactor1");
                var remote2 = system.ActorOf(Props.Create(() => new SomeActor(null, 456)).WithRouter(FromConfig.Instance), "remoteactor2");
                var remote3 = system.ActorOf(Props.Create(() => new SomeActor(null, 789)).WithRouter(FromConfig.Instance), "remoteactor3");

                var hashGroup = system.ActorOf(Props.Empty.WithRouter(new ConsistentHashingGroup(config)));

                Task.Delay(500).Wait();

                var routee1 = Routee.FromActorRef(remote1);
                hashGroup.Tell(new AddRoutee(routee1));

                var routee2 = Routee.FromActorRef(remote2);
                hashGroup.Tell(new AddRoutee(routee2));

                var routee3 = Routee.FromActorRef(remote3);
                hashGroup.Tell(new AddRoutee(routee3));

                Task.Delay(500).Wait();

                for (var i = 0; i < 5; i++)
                {
                    for (var j = 0; j < 7; j++)
                    {
                        var message = new SomeMessage(j, $"remote message: {j}");
                        hashGroup.Tell(message, reply);
                    }
                }

                Console.ReadLine();
            }
        }
    }
}

任何人都可以提供有关我为什么会收到此例外以及如何解决此问题的指导?

因此,F#实现与工作C#实现密切相关。 F# code can be found on GitHub

1 个答案:

答案 0 :(得分:3)

当您启动应用程序时,您可能会读取导致节点解除关联的确切异常:Could not load file or assembly 'System1...

您在路由器配置中定义的是远程部署。这意味着,您可以从一个系统尝试在另一个节点上创建actor并与它们进行通信,就像它们在本地可用一样。虽然这是可能的,但有一个要求:目标演员系统必须知道如何构建演员。由于您的actor在System1中定义并在System2中创建,而System2对SomeActor一无所知,因此失败并导致actor系统解除关联。

您需要将SomeActor类传递给两个系统都可用的共享程序集,以便您的方案可以正常工作。