Akka 和 Play,与非控制器库集成

Akka and Play, integrating with non controller libraries

我很难理解 Akka 与 Play 框架的集成。我想将 Akka actors 集成到我自己创建的非控制器库 class 中,但文档仅提供了一个控制器返回结果的示例 (Play 2.3)。我还没有编写任何代码,因为我对如何前进感到很烦恼。有没有人有关于在控制器外正确使用 Akka 的示例?我找到了这个例子 (Java 8):

import play.libs.F.Promise;
import play.mvc.*;

import static play.libs.F.Promise.promise;

public class Application extends Controller {
    public static Promise<Result> index() {
        return promise(() -> longComputation())
                  .map((Integer i) -> ok("Got " + i));
    }
}

不过看起来和Akka一点关系都没有。我很困惑,我什至不确定我问的这个问题是否正确,对于没有代码示例,我深表歉意。

我的假设是:将上面的代码示例放在我的库 class 中并按指定使用它,像对待任何其他方法调用一样对待 "longRunningComputation()",然后就这样。我当时担心的是我并没有真正利用 Akka 提供的功能。

有没有任何人会推荐的 Akka 教程来提供帮助?

总体

请记住,Akka(实际上)与 Play 没有任何关联或限制。有成千上万的系统建立在 Akka 之上,与 Play 无关。 Akka 和 Play 一起玩得很好。


Akka + Play

在应用程序的 non-controller 部分使用 Akka actors 是完全没问题的。你只需要一种方法将你的控制器连接到你的演员系统。这意味着您需要找到一种方式与您的演员系统中的演员交谈。在 Akka 中(通常)有两种方法可以做到这一点。你要么对演员说(发送)一些东西,要么你问他一些东西。

告诉

说/发送(也称为 telling 或 fire-and-forget)在 Java 中用 actor.tell(message, getSelf()) 完成,在 Scala 中用 actor ! message

import akka.actor.*;
import play.mvc.*;
import play.libs.Akka;
import play.libs.F.Promise;

import static akka.pattern.Patterns.ask;

public class Application extends Controller {

    public static Result index() {
        // select some actor from your system
        ActorSelection actor = Akka.system().actorSelection("user/my-actor");

        // now tell the actor something and do something else because we don't get a reply
        actor.tell("Something");
        return ok("Hello");
    }
}

当然,您绝不仅限于通过控制器的方法联系演员。

整个消息传递过程当然可能非常复杂——这完全取决于您的业务逻辑。上面的 actor my-actor 现在将收到消息并在此时做很多事情 - 转发它,生成 children,杀死自己,进行计算等.

在 Java 中,您将拥有这样的演员:

import akka.actor.UntypedActor;
import akka.event.Logging;
import akka.event.LoggingAdapter;

public class MyUntypedActor extends UntypedActor {
  LoggingAdapter log = Logging.getLogger(getContext().system(), this);

  public void onReceive(Object message) throws Exception {
    if (message instanceof String) {
      log.info("Received String message: {}", message);
      // do whatever you want with this String message
    } else
      unhandled(message);
  }
}

询问

询问完成...惊喜.. 询问模式 - 在 Scala 中 actor ? message.

您已经在 Java 中找到了如何操作的示例。请记住,这次你会得到一些回报。这就是so-calledFuture。一旦这个未来完成(成功),你就会得到你的结果。然后你可以 map 这个结果到其他一些结果。现在看看为什么会有 map() 调用?

import akka.actor.*;
import play.mvc.*;
import play.libs.Akka;
import play.libs.F.Promise;

import static akka.pattern.Patterns.ask;

public class Application extends Controller {

    public static Promise<Result> index() {
        // select some actor from your system
        ActorSelection actor = Akka.system().actorSelection("user/my-actor");

        // now ask the actor something and do something with the reply
        return Promise.wrap(ask(actor, "how are you?", 1000))
                      .map(response -> ok(response.toString()));
    }
}

个人经验的一些笔记:

  • Akka 文档是您的朋友
  • 查看 WebSocket 连接用例 - 为自己构建一个演示 Play 应用程序,您可以在其中支持 WebSocket 并且每个连接都由一个参与者处理。现在想想一个聊天应用程序——一旦我在 WebSocket 上发送了一些东西,我希望该应用程序的每个其他用户都能收到它——现在这对 "hello-world-Akka actors" 来说是很好的情况,不是吗