Akka HTTP 只响应 4 个请求

Akka HTTP responds only to 4 requests

我写了一个简单的 actor,它下载一个网页并将这个页面的正文发送给它的发送者。我使用 Akka HTTP 来构建 HTTP 请求和处理 HTTP 响应。这是我的代码:

class Downloader(uri: String) extends Actor {

  import akka.pattern.pipe
  import context.dispatcher

  final implicit val materializer: ActorMaterializer = ActorMaterializer(ActorMaterializerSettings(context.system))

  val http = Http(context.system)
  http.singleRequest(HttpRequest(uri = uri)) pipeTo self
  println(s"SENDING request to $uri")

  def receive = {
    case HttpResponse(StatusCodes.OK, headers, entity, _) =>
      println(s"HttpResponse: SUCCESS")
      val body = entity.dataBytes.runFold(ByteString(""))(_ ++ _) map (bytes => bytes.decodeString(ByteString.UTF_8)) foreach println
      sender() ! body
      context.stop(self)

    case HttpResponse(code, _, _, _) =>
      println(s"HttpResponse: FAILURE")
      context.stop(self)
  }
}

在主程序中,我创建了 10 个开始在构造函数中下载网页的演员。

val system = ActorSystem("akkaHttpClient")
for (i <- 1 to 10)
  system.actorOf(Props(classOf[Downloader], "http://akka.io"), s"downloader-$i")

Thread.sleep(20000)

val termFuture = system.terminate()
Await.ready(termFuture, Duration.Inf)

不幸的是,创建的 10 个演员中只有 4 个得到回复:

SENDING request to http://akka.io
SENDING request to http://akka.io
SENDING request to http://akka.io
SENDING request to http://akka.io
SENDING request to http://akka.io
SENDING request to http://akka.io
SENDING request to http://akka.io
SENDING request to http://akka.io
SENDING request to http://akka.io
SENDING request to http://akka.io
HttpResponse: SUCCESS
HttpResponse: SUCCESS
HttpResponse: SUCCESS
HttpResponse: SUCCESS

怎么了?我是不是忘记释放一些资源了?

这是使用 Akka HTTP 同时下载多个网页的正确方法吗?

您实际上没有等待响应折叠完成就杀死了演员。以下应该更好用:

  def receive = {
    case HttpResponse(StatusCodes.OK, headers, entity, _) =>
      println(s"HttpResponse: SUCCESS")
      entity.dataBytes.runFold(ByteString(""))(_ ++ _) map (bytes => bytes.decodeString(ByteString.UTF_8)) foreach { s =>
        println(s)
        context.stop(self)
      }

    case HttpResponse(code, _, _, _) =>
      println(s"HttpResponse: FAILURE")
      context.stop(self)
  }

为什么有 4 个请求? 4 是您的底层客户端连接池可以建立的最大连接数,根据参考 configuration.