首页 > 解决方案 > 尝试向 Akka 集群发送请求时,Play Controller 抛出 AskTimeoutException

问题描述

我是初学者,所以请多多包涵。我正在尝试让我的 Play Controller 与我的后端 Akka 集群进行通信。html get 请求被路由到我的控制器中的以下方法:

    public CompletionStage<Result> createSession(int connectionId){
        return FutureConverters.toJava(ask(shardRegion, new CreateSessionMessage(connectionId), 2000))
                .thenApply(response -> ok((String) response));
    }

在哪里

@Inject
    public ConnectionController(ActorSystem system) {
//other things
shardRegion = system.actorSelection("akka.tcp://sharding@127.0.0.1:2551/user/connection"); 
}

我的 Akka 集群正在运行,我可以看到三个节点不断地互相闲聊。

问题是调用 createSession 时出现以下错误: play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution exception[[CompletionException: akka.pattern.AskTimeoutException: Ask timed out on [ActorSelection[Anchor(akka:// application/deadLetters), Path(/user/connection)]] [2000 ms] 之后。[com.vegaspin.actors.connection.ConnectionActorMessage$CreateSessionMessage] 类型的消息。一个典型的原因AskTimeoutException是收件人演员没有发送回复。]]

我的 Akka 集群称为“分片”。我不确定为什么在错误消息中显示 akka://application/deadLetters

这是创建“连接”集群分片的代码

    private static ActorRef setupConnectionClusterSharding(ActorSystem actorSystem) {
        ClusterShardingSettings settings = ClusterShardingSettings.create(actorSystem);
        return ClusterSharding.get(actorSystem).start(
                "connection",
                SpringExtProvider.get(actorSystem).props("ConnectionActor"),
                settings,
                ConnectionActorMessage.messageExtractor()
        );
    }

请问我做错了什么?

标签: playframeworkakka-cluster

解决方案


好的,我现在通过了这个障碍。我想我不妨与其他人分享,希望答案对某人有所帮助。问题实际上是我在注入 Play 的 ActorSystem 而实际上我需要配置自己的。所以这就是我所做的 1. 我在 Play 的 conf/application.config 中添加了

play.akka.actor-system = "sharding" 

这是我在端口 2551、2552 和 0 上运行的 Akka 集群的名称。我还在同一个 application.config 文件中的 Akka 块中添加了以下信息。

  actor {
    provider = "akka.remote.RemoteActorRefProvider" # offer the provider
  }

  remote {
    enabled-transports = ["akka.remote.netty.tcp"] 
    netty.tcp {
      hostname = "127.0.0.1" # your host
      port = 2553 # port
    }
  }

如您所见,我必须更改端口以避免端口绑定异常。我在其他线程的有用评论之一中读到了这一点。

这解决了问题,我继续处理一个新问题,这是在 Akka 集群中引发的异常

[INFO] [04/27/2019 13:02:05.329] [sharding-akka.actor.default-dispatcher-23] [akka://sharding/user/connection] Message [com.actors.connection.ConnectionActorMessage$CreateSessionMessage] from Actor[akka.tcp://sharding@127.0.0.1:2553/temp/$a] to Actor[akka://sharding/user/connection] was not delivered. [3] dead letters encountered. If this is not an expected behavior, then [Actor[akka://sharding/user/connection]] may have terminated unexpectedly, This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.

所以至少我现在可以看到我的 Play 控制器确实向我的后端 AkkaCluster 中的连接分片发送了一条消息。但是我发现了,如果我错了,请纠正我,如果您在分片区域内创建了您的演员,您不应该使用他们的 /user/{actorType}(例如 /user/connection)从外部调用他们,而是你应该使用 /system/{ClusterName}/{ActorType},(例如 /system/sharding/connection 在我的例子中)所以我改变了我的代码

public CompletionStage<Result> createSession(int connectionId){
        shardRegion = system.actorSelection("akka.tcp://sharding@127.0.0.1:2551/**user**/connection");
        return FutureConverters.toJava(ask(shardRegion, new CreateSessionMessage(connectionId), 2000))
                .thenApply(response -> ok((String) response));
    }

public CompletionStage<Result> createSession(int connectionId){
        shardRegion = system.actorSelection("akka.tcp://sharding@127.0.0.1:2551/**system/sharding**/connection");
        return FutureConverters.toJava(ask(shardRegion, new CreateSessionMessage(connectionId), 2000))
                .thenApply(response -> ok((String) response));
    }

在让 Play 控制器在其他地方调用 Akka 分片区域来创建演员时,这是正确的理解吗?


推荐阅读