Akka HTTP仅响应4个请求

时间:2017-01-14 14:26:53

标签: scala akka-stream akka-http

我写了一个简单的演员,它下载一个网页并将此页面的正文发送给发件人。我使用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个开始在构造函数中下载网页的actor。

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同时下载多个网页的正确方法吗?

1 个答案:

答案 0 :(得分:5)

你正在杀死演员而没有真正等待完成响应折叠。以下应该会更好:

  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