我写了一个简单的演员,下载网页并将此页面的正文发送给发件人.我使用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同时下载多个网页的正确方法吗?
你正在杀死演员而没有真正等待完成响应折叠.以下应该更好:
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是根据参考配置,基础客户端连接池可以建立的最大连接数.