如何在Actor的onReceive方法中执行异步数据库插入?

时间:2014-07-29 11:39:00

标签: java playframework akka ebean

我有一个Play框架2应用程序也使用Akka。我有一个Actor从远程系统接收消息,这些消息的数量可能非常巨大。收到消息后,我将其记录到数据库中(使用内置的Ebean ORM),然后继续处理它。我不在乎,这个数据库日志工作的速度有多快,但绝对不应该阻止进一步的处理。这是一个简化的代码示例:

public class MessageReceiver extends UntypedActor {

    @Override
    public void onReceive(Object message) throws Exception {
        if (message instanceof ServerMessage) {
            ServerMessage serverMessage = (ServerMessage) message;
            ServerMessageModel serverMessageModel = new ServerMessageModel(serverMessage);
            serverMessageModel.save();
            //now send the message to another actor for further processing
        } else {
            unhandled(message);
        }
    }
}

据我所知,数据库插入在此实现中是阻塞的,因此它无法满足我的需求。但我无法弄清楚如何让它解锁。我已经阅读过关于Future类的内容,但我无法使其工作,因为它应该返回一些值,serverMessageModel.save();返回void。我明白写了很多消息一个接一个地进入数据库是不合适的,但目前这不是问题。

我是对的,这个实现是阻止的吗?如果是,我怎么能让它异步运行?

3 个答案:

答案 0 :(得分:2)

未来的解决方案对我来说似乎很好。我没有使用过Java的Futures,但如果你肯定需要一些返回值,你可以返回任意的Integer或String。

其他选项是将该消息发送给其他可以保存到数据库的actor。然后你应该确保那个演员的邮箱不会溢出。

您是否考虑过此akka-persistence?也许这适合你的用例。

答案 1 :(得分:1)

如果你想使用Future - 使用Callable(匿名类)构造一个Akka Future,其apply()将实际实现db保存代码。实际上,您可以将所有这些(future creation和apply())放在ServerMessageModel类中 - 也许称之为asynchSave()。你的未来可能是未来,其中状态是asynchSave的结果......

public Future<Status> asyncSave(...) { /* should the params be ServerMessageModel? */
  return future(new Callable<Status>() {
     public Status call() {
        /* do db work here */
     }
 }

在你的onReceive中你可以继续告诉另一个演员。注意:如果你想确保在未来返回后向另一个演员发出告诉,那么你可以使用Future的onSuccess。

Future<Status> f = serverMessageModel.asyncSave();
f.onSuccess(otherActor.tell(serverMessage, self());

您也可以进行故障处理...有关详细信息,请参阅http://doc.akka.io/docs/akka/2.3.4/java/futures.html

希望有所帮助。

答案 2 :(得分:0)

使用Martin Krassers akka-persistence扩展和我的jdbc持久性提供程序akka persistence jdbc https://github.com/dnvriend/akka-persistence-jdbc

持续保持actor状态