Akka 经典 - 发送自定义类消息类型

Posted

技术标签:

【中文标题】Akka 经典 - 发送自定义类消息类型【英文标题】:Akka classic - sending custom class message types 【发布时间】:2021-08-15 18:19:08 【问题描述】:

我正在尝试遵循在 Akka Actor 之间发送消息并阅读以下内容的最佳实践:

https://github.com/akka/akka/blob/v2.6.15/akka-docs/src/test/java/jdocs/actor/ActorDocTest.java#L101-L129

https://doc.akka.io/docs/akka/current/actors.html

似乎最好的做法是定义一个包含要发送的消息的静态类。

通过阅读文档,我定义了以下内容:

import akka.event.Logging;
import akka.event.LoggingAdapter;
import akka.persistence.AbstractPersistentActor;

class RecoveryActor extends AbstractPersistentActor 

    public static class Msg1 
    public static class Msg2 

    private final LoggingAdapter log = Logging.getLogger(getContext().getSystem(), this);

    /**
     * Handler that will be called on recovery.
     * @return
     */
    @Override
    public Receive createReceiveRecover() 
        return receiveBuilder()
                .match(Msg1.class, this::receiveMsg1)
                .match(Msg2.class, this::receiveMsg2)
                .build();
    

    private void receiveMsg1(Msg1 msg) 
        log.info("in receive message 1");
    

    private void receiveMsg2(Msg2 msg) 
        log.info("in receive message 2");
    

    /**
     * The normal receive method.
     * @return
     */
    @Override
    public Receive createReceive() 
        return receiveBuilder()
                .match(String.class, s -> s.equals("cmd"), s -> persist("evt", this::handleEvent))
                .build();
    

    private void handleEvent(String event) 
        System.out.println("in handle event");
    

    @Override
    public String persistenceId() 
        return "simple-accountant"; //best practice, the id should be unique.
    


但我不确定如何使用Msg1Msg2 发送消息

我已经定义了一个新类来发送消息:

import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Props;

public class ActorMessaging 

    public static void main(String args[])
        final ActorSystem system = ActorSystem.create("example");
        final ActorRef actor = system.actorOf(Props.create(RecoveryActor.class));

        actor.tell(RecoveryActor.Msg1);

    

但编译器错误失败:

java: cannot find symbol
  symbol:   variable Msg1
  location: class recoverydemo.RecoveryActor

如何向Msg1 类型的 Actor 发送消息?

这是在参与者之间发送消息并将消息包装在自定义类中的最佳做法吗?

【问题讨论】:

【参考方案1】:

actor.tell 正在接受对象。 RecoveryActor.Msg1 不是那个,它甚至不是类引用。尝试像这样发送Msg1 的实例怎么样:

actor.tell(new RecoveryActor.Msg1(), actorRef)

为了与远程actor“交谈”,您首先需要获取对它的引用。这通常由ActorSystem 完成

【讨论】:

谢谢,但是编译失败,编译错误是:'akka.actor.ActorRef'中的''tell(java.lang.Object, akka.actor.ActorRef)'不能应用于'( recoverydemo.RecoveryActor.Msg1)' 。我添加了发件人:'actor.tell(new RecoveryActor.Msg1() , actor);'但未收到消息,并且将以下内容输出到日志:'[example-akka.actor.default-dispatcher-7] - 来自 Actor[akka://example/user/$a 的消息 [recoverydemo.RecoveryActor$Msg1] #901889227] 到 Actor[akka://example/user/$a#901889227] 未处理。 [1] 遇到死信。'【参考方案2】:

我犯了一个愚蠢的错误。我覆盖了不正确的方法。我应该改写createReceive

    public Receive createReceive() 

        return receiveBuilder()
                .match(RecoveryActor.Msg1.class, this::receiveMsg1)
                .match(Msg2.class, this::receiveMsg2)
                .build();
        
//        return receiveBuilder()
//                .match(String.class, s -> s.equals("cmd"), s -> persist("evt", this::handleEvent))
//                .build();
    

【讨论】:

以上是关于Akka 经典 - 发送自定义类消息类型的主要内容,如果未能解决你的问题,请参考以下文章

SendMessage发送自定义消息及消息响应(VC版)

第四十四课发送自定义事件(下)

JSON 写入错误中的类型无效,尝试通过 JSON 将自定义类发送到 .NET Web 服务

Flutter Firebase 上传自定义类列表

讨论:动态链接库如何给主程序发送自定义消息?

AKKA Actor创建