我写了一个简单的演员,它下载一个网页并将此页面的正文发送给发件人。我使用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同时下载多个网页的正确方法吗?
答案 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。