【问题标题】:Dead letters on unrelated ActorRefs when sending message from remotely deployed actor从远程部署的 Actor 发送消息时,无关 ActorRefs 上的死信
【发布时间】:2019-10-05 21:36:41
【问题描述】:

我遇到了一个问题,在应用程序运行一段时间后,发送到 akka 集群中远程参与者的消息具有非常高的延迟(10+ 秒)。日志表明提供者试图解析旧演员ActorPaths,这与我实际上将消息发送到的ActorRef 无关。您可以在问题底部找到日志摘录。

我的应用程序包含 3 个 ActorSystems,它们通过 akka-cluster 进行交互,远程传输通过 artery 配置,我将在下面提供我的 applications.conf(s)。

我以编程方式将远程actor创建为本地actor (like so),然后再次从子actor执行相同操作(因此最终得到不同ActorSystems的父子孙子) .

如果我在应用程序一开始就从孙子向其父级发送消息,我确实会以合理的延迟(

但是,如果我在三个系统上启动(并杀死)其他参与者,则此类消息的消息延迟变得不切实际。我认为这与ActorSystemLocalActorRefProviders 之一试图解决以前创建的(并且已经死的)演员的ActorPaths 有关。我将发布一段显示此类情况的应用程序日志摘录。

当我专门向(远程)ActorRef 发送消息时,我不明白为什么需要解决任何其他引用问题,并且非常感谢任何帮助或建议。

// application.conf(s)

akka {
  actor {
    provider = "cluster"
    serializers {
      kryo = "com.twitter.chill.akka.AkkaSerializer"
    }
    serialization-bindings {
      "java.io.Serializable" = kryo
      "akka.actor.Props" = kryo
    }
    enable-additional-serialization-bindings = on
  }
  remote {
    log-sent-messages = on
    log-received-messages = on
    log-remote-lifecycle-events = off
    artery {
      enabled = on
      transport = tcp
      canonical.hostname = "127.0.0.1"  // these obv differ depending on the system
      canonical.port = 7900
    }
  }
  cluster {
    seed-nodes = [  // set in AbstractSystem
      "akka://experiments-master@127.0.0.1:7900"
    ],
    # WARN Don't use auto-down feature of Akka Cluster in production.
    # auto-down-unreachable-after = 10s
  }
  loglevel = "DEBUG"
}

// ParentActor.java
public class ParentActor extends ClusterAwareActor {

    public static final String DEFAULT_NAME = "ParentActor";

    public static Props props() {
        return Props.create(TestActor.class, () -> new TestActor());
    }

    TestActor() {}

    private final Instant initTime = Instant.now();


    @Override
    public Receive createReceive() {
        return receiveBuilder()
                .match(ClusterEvent.CurrentClusterState.class, this::handle)
                .match(ClusterEvent.MemberUp.class, this::handle)
                .build().orElse(super.createReceive());
    }

    @Override
    protected void handle(ClusterEvent.CurrentClusterState msg) {
        super.handle(msg);

        Collection<ActorRef> children = this.remoteActorsOf(ChildActor.props(), ChildActor.DEFAULT_NAME, SystemRole.SLAVE, true);
    }
}
// excerpt from ClusterAwareActor
// [ ... ]
protected Collection<ActorRef> remoteActorsOf(Props props, String actorName, SystemRole role, boolean skipOwnSystem) {
    Collection<ActorRef> results = Lists.newArrayList();
    Collection<Member> members = this.systemRoleMemberMap.get(role);

    for (Member member : members) {
        if (cluster.selfMember().equals(member) && skipOwnSystem) continue;

        Props remoteProps = props.withDeploy(new Deploy(new RemoteScope(member.address())));

        if (actorName != null) {
            results.add(this.getContext().actorOf(remoteProps, CustomStringUtils.randomActorName(actorName))); // this is just so I don't have name clashes
        } else {
            results.add(this.getContext().actorOf(remoteProps));
        }
    }
    return results;
}
// ChildActor.java
public class ChildActor extends ClusterAwareActor {

    public static final String DEFAULT_NAME = "ChildActor";

    public static Props props() {
        return Props.create(TestActorTwo.class, () -> new TestActorTwo());
    }

    TestActorTwo() {}

    private final Instant initTime = Instant.now();

    @Override
    public Receive createReceive() {
        return receiveBuilder()
                .match(ClusterEvent.CurrentClusterState.class, this::handle)
                .match(Messages.PongWithSendTime.class, this::handle)
                .build().orElse(super.createReceive());
    }

    @Override
    protected void handle(ClusterEvent.CurrentClusterState msg) {
        super.handle(msg);
        Collection<ActorRef> children = this.remoteActorsOf(GrandChildActor.props(), SystemRole.SLAVE, true);
        Preconditions.checkState(children.size() == 1);
        Lists.newArrayList(children).get(0).tell(new Messages.PingMessage(), self());
        log().info("[{}] Sent PING at {} ms", DEFAULT_NAME, Duration.between(this.initTime, Instant.now()).toMillis());
    }

    private void handle(Messages.PongWithTime msg) {
        log().info("[{}] Received PONG at {} ms, transmission took ~ {} ms",
                DEFAULT_NAME,
                Duration.between(this.initTime, Instant.now()).toMillis(),
                Duration.between(msg.getSendTime(), Instant.now()).toMillis());
    }
}
// GrandChildActor.java
public class GrandChildActor extends AbstractLoggingActor {

    public static final String DEFAULT_NAME = "GrandChildActor";

    public static Props props() {
        return Props.create(PongSayer.class, () -> new PongSayer());
    }

    PongSayer() {}

    @Override
    public Receive createReceive() {
        return receiveBuilder()
                .match(Messages.PingMessage.class, this::handle)
                .build().orElse(super.createReceive());
    }

    private void handle(Messages.PingMessage __) {
        getContext().getParent().tell(new Messages.PongWithTime(Instant.now()), self());
    }
}

只要之前没有创建和杀死其他参与者,所有这些都可以正常工作(即消息通过得相当快)。如果是这种情况,单个消息的传输(仅包装 Instant)可能需要 10 到 30 秒。

您可以在此处查看来自ActorSystem 的日志,其中包含ChildActor

[INFO] [10/05/2019 22:37:12.431] [dispatcher] [akka://app@172.18.5.173:7700/remote/akka/app@172.18.5.173:7900/user/ParenteActor/ChildActor] Created GrandChildActor and sent PingMessage.
[...]
[DEBUG] [10/05/2019 22:37:13.668] [dispatcher] [akka.actor.LocalActorRefProvider(akka://app)] Resolve (deserialization) of path [remote/akka/app@172.18.5.173:7900/user/path/to/other/unrelated/actor] doesn't match an active actor. It has probably been stopped, using deadLetters.
[DEBUG] [10/05/2019 22:37:13.738] [dispatcher] [akka.actor.LocalActorRefProvider(akka://app)] Resolve (deserialization) of path [remote/akka/app@172.18.5.173:7900/user/path/to/other/unrelated/actor] doesn't match an active actor. It has probably been stopped, using deadLetters.
[DEBUG] [10/05/2019 22:37:13.809] [dispatcher] [akka.actor.LocalActorRefProvider(akka://app)] Resolve (deserialization) of path [remote/akka/app@172.18.5.173:7900/user/path/to/other/unrelated/actor] doesn't match an active actor. It has probably been stopped, using deadLetters.
[...] // there is a metric ton of these
[DEBUG] [10/05/2019 22:37:32.498] [dispatcher] [akka.actor.LocalActorRefProvider(akka://app)] Resolve (deserialization) of path [remote/akka/app@172.18.5.173:7900/user/path/to/other/unrelated/actor] doesn't match an active actor. It has probably been stopped, using deadLetters.
[DEBUG] [10/05/2019 22:37:32.568] [dispatcher] [akka.actor.LocalActorRefProvider(akka://app)] Resolve (deserialization) of path [remote/akka/app@172.18.5.173:7900/user/path/to/other/unrelated/actor] doesn't match an active actor. It has probably been stopped, using deadLetters.
[DEBUG] [10/05/2019 22:37:32.638] [dispatcher] [akka.actor.LocalActorRefProvider(akka://app)] Resolve (deserialization) of path [remote/akka/app@172.18.5.173:7900/user/path/to/other/unrelated/actor] doesn't match an active actor. It has probably been stopped, using deadLetters.
[DEBUG] [10/05/2019 22:37:32.708] [dispatcher] [akka.actor.LocalActorRefProvider(akka://app)] Resolve (deserialization) of path [remote/akka/app@172.18.5.173:7900/user/path/to/other/unrelated/actor] doesn't match an active actor. It has probably been stopped, using deadLetters.
// before finally
[INFO] [10/05/2019 22:37:32.711] [dispatcher] [akka://app@172.18.5.173:7700/remote/akka/app@172.18.5.173:7900/user/ParentActor/ChildActor] Received Lookup response. Transmission took 20234 ms.

【问题讨论】:

    标签: java akka akka-cluster


    【解决方案1】:

    由于信息不完整且经过编辑,无法确定确切的答案,但是 Akka 不会尝试解析不相关的 ActorRefs。该消息表明集群的另一个节点实际上正在向那些死去的参与者发送消息。

    关于时间:您显示的代码测量父母开始和收到任何 pong 消息之间的时间,通过集群消息给出的触发器可能是任意时间跨度。

    【讨论】:

    • 感谢您的帮助。由于这是一个更大的代码库的一部分,我将把一个 MWE 放在一起并在这里链接它。关于。时间测量:触发消息是子级实例化后立即从子级向子级发送的 Ping。这反过来在接收到 CurrentClusterState 事件时发生。我还通过比较 GrandChild 发送消息的时间与 Child 接收消息的时间来记录(估计)传输时间。
    猜你喜欢
    • 1970-01-01
    • 2016-06-12
    • 1970-01-01
    • 2015-02-13
    • 2021-09-11
    • 2020-11-27
    • 1970-01-01
    • 2014-07-29
    • 2019-10-17
    相关资源
    最近更新 更多