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



我们从使用Camel HTTP4转向Akka HTTP,虽然我们现在能够更好地控制错误,但考虑到Akka HTTP(客户端(中的所有可调参数,很难获得更好的性能。

我们有一个参与者,它接收消息,向外部服务发出HTTP GET请求(轻松管理超过1500 RPS(,然后使用http响应体作为字符串进行响应。

我们现在的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 实例、主机连接池下的所有其他参数,但我们不能变得更好。

欢迎任何建议!

不要混合和匹配并发

据推测,您的查询功能只是向Actor发送消息并等待响应:

//what your code may look like now
object Message
val queryActorRef : ActorRef = ???
val responseBody : Future[String] = (queryActorRef ? Message).mapTo[String]

但这是不必要的。 在此用例中使用Actor的唯一原因是保护有限的资源。 但基础 http 连接池会为您处理资源利用率。 删除Actor中介将允许您单独使用期货:

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
}

最新更新