我有一个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
。我明白写了很多消息一个接一个地进入数据库是不合适的,但目前这不是问题。
我是对的,这个实现是阻止的吗?如果是,我怎么能让它异步运行?
答案 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状态