我正在尝试在我的 Play 2.5 应用程序中使用 Akka 演员和依赖注入。我基本上遵循了那个文档,这里是我的代码的一瞥:
演员
基本上,我有一个简单的参与者,它接收一些数据,处理它,然后将其发送回调用者。
package actors
import akka.actor._
import akka.pattern.{AskTimeoutException, ask}
import akka.util.Timeout
import javax.inject._
import com.google.inject.assistedinject.Assisted
import play.api.Configuration
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext
import scala.concurrent.Future
object ServiceActor {
val ConfigKey = "actors.path" // remote actor path
trait Factory {
def apply(key: String): Actor
}
}
class ServiceActor @Inject()(configuration: Configuration,
actorSystem: ActorSystem,
@Assisted key: String)
(implicit val ec: ExecutionContext)
extends Actor {
import ServiceActor._
implicit val timeout = Timeout(5.minutes)
def receive = {
case data: SomeData => sender ! someFunction(data)
}
// implemented in the real code, omitted because not important for the question
def someFunction = ???
}
模块
根据文档,我需要制作一个简单的模块并激活它。这是模块:
package modules
import com.google.inject.AbstractModule
import play.api.libs.concurrent.AkkaGuiceSupport
import actors.ServiceActor
class ServiceModule extends AbstractModule with AkkaGuiceSupport {
def configure = {
bindActor[ServiceActor]("service-actor")
}
}
然后我通过将以下行添加到application.conf
:
play.modules {
enabled += modules.ServiceModule
}
控制器
最后,我尝试在控制器中使用演员:
package controllers
import akka.actor._
import akka.pattern.ask
import akka.util.Timeout
import javax.inject._
import play.api.mvc._
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext
@Singleton
class SearchController @Inject()(@Named("service-actor") serviceActor: ActorRef)
(implicit ec: ExecutionContext)
extends Controller {
implicit val timeout = Timeout(5.minutes)
def search(param: String) = Action.async {
val request = SomeRequestType(param)
(serviceActor ? request).mapTo[SomeResponseType] map { result =>
Ok(result.toString)
}
}
}
据我所知,我已经完美地遵循了文档,但是调用控制器给了我这个错误:
[AskTimeoutException: Recipient[Actor[akka://application/user/service-actor#-366470383]]
had already been terminated.
Sender[null] sent the message of type "some.namespace.SomeRequestType".]
据我了解,错误是关于演员是 a 的null
,我们无法向它发送消息。虽然错误代码说“已经被终止”,但看起来演员从来没有被启动过。
我不确定首先要看哪里,我做错了什么,因为我没有使用 Guice 的经验。
问题是,我做错了什么?为什么actor没有启动,或者如果它确实已经终止,为什么它会被终止?我该如何解决?
非常感谢。