Play + Akka - присоединиться к кластеру и попросить актера на другой ActorSystem - PullRequest
0 голосов
/ 27 июня 2018

Я могу заставить приложение Play присоединиться к существующему кластеру Akka, а затем сделать запрос вызова актеру, работающему в другой системе ActorSystem, и получить результаты обратно. Но у меня проблемы с парой вещей -

  1. Я вижу ниже в журналах, когда игра пытается присоединиться к кластеру. Я подозреваю, что Play запускает свой собственный кластер akka? Я действительно не уверен, что это значит.

    Не удалось зарегистрировать кластерный JMX MBean с name=akka:type=Cluster, так как он уже зарегистрирован. Если вы используете несколько кластеров В той же JVM установите 'akka.cluster.jmx.multi-mbeans-in-same-jvm = on' в config`

  2. Прямо сейчас я переинициализирую актерскую систему каждый раз, когда приходит запрос к Контроллеру, что, как я знаю, является неправильным способом сделать это. Я новичок в Scala, Akka, Play вещь, и мне трудно понять, как заставить его работать синглтоном и вводить его в мой контроллер.

Пока у меня есть это -

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}
}

1 Ответ

0 голосов
/ 23 июля 2018

Ответы

  1. Обратитесь к этому URL. https://www.playframework.com/documentation/2.6.x/ScalaAkka#Built-in-actor-system-name содержит подробную информацию о настройке имени системы актера.

  2. Вы не должны инициализировать систему акторов при каждом запросе, используйте Play injected actor system в классе Application. Если вы хотите настроить систему Actor, вы должны сделать это путем изменения конфигурации AKKA. Для этого, Вы должны создать свой собственный ApplicationLoader, расширяющий GuiceApplicationLoader, и переопределить метод builder, чтобы иметь собственную конфигурацию AKKA. Остальные вещи позаботились о Игре, как о введении этой системы актеров в Приложение для вас.

См. Ниже URL

https://www.playframework.com/documentation/2.6.x/ScalaDependencyInjection#Advanced:-Extending-the-GuiceApplicationLoader

...