2016-03-21 5 views
3


Я использую Акку-клиент, мой build.sbt конфигурация:балансировки нагрузки Акка-клиент

scalaVersion := "2.11.7" 
libraryDependencies += "com.typesafe.akka" % "akka-actor_2.11" % "2.4.2" 
libraryDependencies += "com.typesafe.akka" % "akka-http-experimental_2.11" % "2.4.2" 
libraryDependencies += "com.typesafe.akka" % "akka-http-spray-json-experimental_2.11" % "2.4.2" 
libraryDependencies += "com.typesafe.akka" % "akka-slf4j_2.11" % "2.4.2" 

Я обнажая простую REST API только с одним GET URL-адрес
обув является функция, которая возвращает будущий

implicit val actorSystem = ActorSystem("system", config) 
implicit val actorMaterializer = ActorMaterializer() 

val route: Route = { 
    get { 
    path("foo") { 
     complete { foo } 
    } 
    } 
} 

веб-сервис, как ожидается, много звонков, и я хочу сделать избыточность службы в случае сбоя, поэтому я хочу, чтобы одновременно выполнялось два экземпляра для обработки всех запросов.

1) Каков наилучший способ иметь два приема веб-сервиса, обрабатывающего запросы одновременно ?, с внешним балансировщиком нагрузки или с некоторой магией (я не знаю) внутри akka/akka-http ?

2) Каковы основные параметры, которые я должен настроить, чтобы улучшить производительность?

ответ

5

Ответ на вопрос this question показывает, как сделать вызов Актера в пределах Route.

Если вы объедините эту технику с возможностями clustering в пределах Akka, вы сможете выполнить свою работу.

Отправляйте свой маршрут на адрес Router, который отправит сообщение в 1 из N remotely deployed Actors (с вашего вопроса это звучит как маршрутизатор round robin - это то, что вы хотите).

class HttpResponseActor extends Actor { 

    def foo : HttpResponse = ??? // Not specified in question 

    override def receive = { 
    case _ : HttpRequest => foo 
    } 
} 

import akka.actor.{ Address, AddressFromURIString } 
import akka.remote.routing.RemoteRouterConfig 

val addresses = Seq(Address("akka.tcp", "remotesys", "otherhost", 1234), 
        AddressFromURIString("akka.tcp://[email protected]:1234")) 

val routerRemote = 
    system.actorOf(RemoteRouterConfig(RoundRobinPool(5), addresses).props(Props[HttpResponseActor])) 

Удаленный Актер отвечает HttpResponse. Этот отзыв может быть go through the Router or directly back to the Route.

Маршрут берет ответ в директиве complete, чтобы вернуться к клиенту.

val route = 
    get { 
    path("foo") { 
     onComplete((routerRemote ? request).mapTo[HttpResponse]) { 
     case Success(response) => complete(response) 
     case Failure(ex) => complete((InternalServerError, s"Actor not playing nice: ${ex.getMessage}")) 
     } 
    } 
    } 
+0

Hi @Ramon, спасибо за ответ !!!, могу я задать вам еще два вопроса? 1) Если я использую актеров, я теряю контроль над потоком, который предоставляют потоки? 2) где мне нужно вызвать функцию foo? –

+0

@GeorgeC, вы можете ответить на этот вопрос. 1) Я не думаю, что ты потеряешь давление, но я не уверен на 100%. Я не знаю эффектов вызова Route 'onComplete', это может быть преобразовано в' mapAsync' или 'mapAsyncAwait'. 2) Я исправил свой ответ, чтобы сохранить вашу оригинальную функцию 'foo'. Счастливый взлом. –