Akka HTTP客户端和Akka actor性能调整

时间:2018-09-28 11:59:25

标签: scala akka akka-http

我们从使用Camel HTTP4迁移到了Akka HTTP,尽管现在我们能够更好地控制错误,但是考虑到Akka HTTP(客户端)中的所有可调参数,要获得更好的性能确实变得非常困难。

我们有一个参与者,该参与者接收消息,向外部服务发出HTTP GET请求(可以轻松管理超过1500 RPS),然后以http响应主体作为String进行响应。

我们目前的最高RPS为650 RPS,即使我们没有收到错误(如先前使用Camel的HTTP4),也无法超过650(与之前使用默认参数的HTTP4的800 RPS相对)。

我们的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
      }
    }

}

我们尝试调整池大小,actor实例以及host-connection-pool下所有其他参数的大小,但情况再好不过了。

欢迎提出任何建议!

1 个答案:

答案 0 :(得分:2)

请勿混用并发并发

大概您的查询功能只是向Actor发送消息并等待响应:

//what your code may look like now

object Message

val queryActorRef : ActorRef = ???

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

但这是不必要的。在此用例中使用Actor的唯一原因是保护有限的资源。但是底层的http连接池可为您处理资源利用率。删除Actor中介将使您可以单独使用Future:

val entityTimeout : FiniteDuration = 10.seconds

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

如果发送给Actor的“消息”具有潜在来源,例如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
  }