Настройка клиента Akka HTTP и актера Akka - PullRequest
0 голосов
/ 28 сентября 2018

Мы перешли от использования Camel HTTP4 к Akka HTTP и, хотя теперь мы можем гораздо лучше контролировать ошибки, становится все труднее добиться лучшей производительности, учитывая все настраиваемые параметры в Akka HTTP (клиент).

У нас есть субъект, который получает сообщения, отправляет HTTP-запрос GET во внешнюю службу (легко может управлять более 1500 RPS), а затем отвечает телом ответа http в виде строки.

Мы ограничены 650RPS прямо сейчас, и даже если мы не получим ошибок (как ранее с верблюдом HTTP4), мы не можем преодолеть эти 650 (в отличие от предыдущих 800 RPS с HTTP4 с использованием параметров по умолчанию).

Наши HTTP-запросысделано с помощью singleRequest:

val httpResponseFuture: Future[HttpResponse] = http.singleRequest(HttpRequest(uri = uri))

val tokenizationResponse = for {
  response <- httpResponseFuture
  body <- Unmarshal(response.entity).to[String]
} yield transformResponse(response.status, body, path, response.headers)

А затем эти параметры настройки дали лучшие результаты (просмотр этих цифр не дает реального улучшения:

akka {

    actor.deployment {
      /HttpClient {
        router = balancing-pool
        nr-of-instances = 7
      }
    }

    http {
      host-connection-pool {
        max-connections = 30
        max-retries = 5
        max-open-requests = 8192
        pipelining-limit = 200
        idle-timeout = 30 s
      }
    }

}

Мы попытались изменить размерпул, экземпляры актера, все остальные параметры в пуле host-connection-pool, но мы не можем получить никакой ставкиer.

Любые предложения приветствуются!

1 Ответ

0 голосов
/ 02 октября 2018

Не смешивать и сопоставлять параллелизм

Предположительно, ваша функция запросов просто отправляет сообщение на Actor и ожидает ответа:

//what your code may look like now

object Message

val queryActorRef : ActorRef = ???

val responseBody : Future[String] = (queryActorRef ? Message).mapTo[String]

Но это не обязательно.Единственная причина использования Actor в этом случае - защита ограниченного ресурса.Но основной пул http-соединений имеет дело с использованием ресурсов для вас.Удаление посредника Actor позволит вам работать только с Futures:

val entityTimeout : FiniteDuration = 10.seconds

val responseBodyWithoutAnActor : Future[String] = 
    http
      .singleRequest(HttpRequest(uri = uri))
      .flatMap(response => response.entity.toStrict(timeout))
      .map(_.data.utf8String)

Streams

Если «сообщения», отправляемые Актору, имеют основной источник,например, Iterable, тогда вы можете использовать потоковую передачу вместо:

type Message = ???

val messagesSource : Iterable[Message] = ???

val uri : String = ???

val poolClientFlow = Http().cachedHostConnectionPool[Promise[HttpResponse]](uri)

val entityParallelism = 10

Source
  .apply(messagesSource)
  .via(poolClientFlow)
  .mapAsync(entityParallelism)(resp.entity.toStrict(entityTimeout).data.utf8String)
  .runForeach { responseBody : String =>
    //whatever you do with the bodies
  }
...