[英]Play + Akka - Join the cluster and ask actor on another ActorSystem
我能夠使Play應用加入現有的Akka集群,然后對在另一個ActorSystem上運行的actor進行詢問,並返回結果。 但是我在幾件事上遇到麻煩-
當游戲嘗試加入集群時,我在日志中看到以下內容。 我懷疑Play正在啟動自己的Akka集群嗎? 我真的不確定這意味着什么。
無法注冊
name=akka:type=Cluster
集群JMX MBean,因為它已被注冊。 如果您在同一個JVM中運行多個集群,請在配置中設置“ akka.cluster.jmx.multi-mbeans-in-same-jvm = on”
現在,每次我收到不正確的方法請求到Controller時,我都會重新初始化actor系統。 我是Scala,Akka和Play的新手,很難弄清楚如何使其成為Singleton服務並注入我的控制器。
到目前為止,我已經知道了-
class DataRouter @Inject()(controller: DataController) extends SimpleRouter {
val prefix = "/v1/data"
override def routes: Routes = {
case GET(p"/ip/$datatype") =>
controller.get(datatype)
case POST(p"/ip/$datatype") =>
controller.process
}
}
case class RangeInput(start: String, end: String)
object RangeInput {
implicit val implicitWrites = new Writes[RangeInput] {
def writes(range: RangeInput): JsValue = {
Json.obj(
"start" -> range.start,
"end" -> range.end
)
}
}
}
@Singleton
class DataController @Inject()(cc: ControllerComponents)(implicit exec: ExecutionContext) extends AbstractController(cc) {
private val logger = Logger("play")
implicit val timeout: Timeout = 115.seconds
private val form: Form[RangeInput] = {
import play.api.data.Forms._
Form(
mapping(
"start" -> nonEmptyText,
"end" -> text
)(RangeInput.apply)(RangeInput.unapply)
)
}
def get(datatype: String): Action[AnyContent] = Action.async { implicit request =>
logger.info(s"show: datatype = $datatype")
logger.trace(s"show: datatype = $datatype")
//val r: Future[Result] = Future.successful(Ok("hello " + datatype ))
val config = ConfigFactory.parseString("akka.cluster.roles = [gateway]").
withFallback(ConfigFactory.load())
implicit val system: ActorSystem = ActorSystem(SharedConstants.Actor_System_Name, config)
implicit val materializer: ActorMaterializer = ActorMaterializer()
implicit val executionContext = system.dispatcher
val ipData = system.actorOf(
ClusterRouterGroup(RandomGroup(Nil), ClusterRouterGroupSettings(
totalInstances = 100, routeesPaths = List("/user/getipdata"),
allowLocalRoutees = false, useRoles = Set("static"))).props())
val res: Future[String] = (ipData ? datatype).mapTo[String]
//val res: Future[List[Map[String, String]]] = (ipData ? datatype).mapTo[List[Map[String,String]]]
val futureResult: Future[Result] = res.map { list =>
Ok(Json.toJson(list))
}
futureResult
}
def process: Action[AnyContent] = Action.async { implicit request =>
logger.trace("process: ")
processJsonPost()
}
private def processJsonPost[A]()(implicit request: Request[A]): Future[Result] = {
logger.debug(request.toString())
def failure(badForm: Form[RangeInput]) = {
Future.successful(BadRequest("Test"))
}
def success(input: RangeInput) = {
val r: Future[Result] = Future.successful(Ok("hello " + Json.toJson(input)))
r
}
form.bindFromRequest().fold(failure, success)
}
}
akka {
log-dead-letters = off
log-dead-letters-during-shutdown = off
actor {
provider = "akka.cluster.ClusterActorRefProvider"
}
remote {
log-remote-lifecycle-events = off
enabled-transports = ["akka.remote.netty.tcp"]
netty.tcp {
hostname = ${myhost}
port = 0
}
}
cluster {
seed-nodes = [
"akka.tcp://MyCluster@localhost:2541"
]
} seed-nodes = ${?SEEDNODE}
}
答案
引用此URL。 https://www.playframework.com/documentation/2.6.x/ScalaAkka#Built-in-actor-system-name包含有關配置actor系統名稱的詳細信息。
您不應在每個請求上初始化actor系統,而應在Application類中使用Play注入的actor系統,如果要自定義Actor系統,則應通過修改AKKA配置來實現。 為此,您應該創建自己的ApplicationLoader擴展GuiceApplicationLoader並重寫builder方法以具有自己的AKKA配置。 Play照顧的其他事情,例如在您的Application中注入這個actor系統。
請參閱下面的URL
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.