[英]How to make parallel Http request using Akka-Http?
我是Scala的新手,正在嘗試實現一個可獲取數千個URL的庫。 我的工作是從這些URL下載內容。 我本來會選擇簡單的scalaj-http
庫,但它不能滿足我的目的。 我附帶的代碼是這樣的:
class ProxyHttpClient {
def get(url: String, proxy: ProxySettings,urlDownloaderConfig:
UrlDownloaderConfig)(implicit ec: ExecutionContext): Either[HttpError,
HttpSuccessResponse] = {
implicit val system: ActorSystem = ActorSystem()
implicit val materializer: ActorMaterializer = ActorMaterializer()
val auth = headers.BasicHttpCredentials(proxy.userName,
proxy.secret)
val httpsProxyTransport =
ClientTransport.httpsProxy(InetSocketAddress.createUnresolved(
proxy.host, proxy.port), auth)
val settings =
ConnectionPoolSettings(system).withTransport(httpsProxyTransport)
val response: Future[HttpResponse] =
Http().singleRequest(HttpRequest().
withMethod(HttpMethods.GET).withUri(url), settings = settings)
val data: Future[Either[HttpError, HttpSuccessResponse]] = `response.map {`
case response@HttpResponse(StatusCodes.OK, _, _, _) => {
val content: Future[String] = Unmarshal(response.entity).to[String]
val finalContent = Await.ready(content, timeToWaitForContent).value.get.get.getBytes
Right(HttpSuccessResponse(url, response.status.intValue(), finalContent))
}
case errorResponse@HttpResponse(StatusCodes.GatewayTimeout, _, _, _) => Left(HttpError(url, errorResponse.status.intValue(), errorResponse.entity.toString))
}
val result: Try[Either[HttpError, HttpSuccessResponse]] = Await.ready(data, timeToWaitForResponse).value.get
val pop: Either[HttpError, HttpSuccessResponse] = try {
result.get
} catch {
case e: Exception => Left(HttpError(url, HttpStatus.SC_INTERNAL_SERVER_ERROR, e.getMessage))
}
pop
}
}
為了調用我正在使用的get
方法
val forkJoinPool = new scala.concurrent.forkjoin.ForkJoinPool(8)
picList.par.tasksupport = new ForkJoinTaskSupport(forkJoinPool)
picList.par.map(testUrl => {
val resp = get(url, Option(proxy))
})
它運行了好幾次,但是當我嘗試調用1000個url的方法來獲取批處理大小為100的圖像時,它拋出了錯誤。 在那之后,即使對於單個URL,我也遇到同樣的錯誤。
**java.lang.OutOfMemoryError: unable to create new native thread**
我是否應該在這里使用actor而不是actorsystem並為其專門分配一個調度程序?
由於我持有的是二進制圖像,因此在達到其目的后,我必須注意將其從內存中刪除嗎?
代碼段將更有用。 提前致謝
我嘗試遵循人們建議使用的在線建議
val blockingExecutionContext = system.dispatchers.lookup("blocking-dispatcher")
但是當我嘗試時, system.dispatchers.lookup
返回的是MessageDispacther類型。
implicit val system: ActorSystem = ActorSystem()
val ex: MessageDispatcher =system.dispatchers.lookup("io-blocking-dispatcher")
我是否缺少任何庫或導入文件?
您的問題很可能與為每個http調用創建actor系統有關。 Actor系統通常是每個應用程序一個。
做一個小的重構,然后嘗試一下。
class ProxyHttpClient() {
private implicit val system: ActorSystem = ActorSystem()
private implicit val materializer: ActorMaterializer = ActorMaterializer()
def get(url: String, proxy: ProxySettings,urlDownloaderConfig:
UrlDownloaderConfig)(implicit ec: ExecutionContext): Either[HttpError,
HttpSuccessResponse] = {???}
}
或提取actor系統並將其作為隱式參數傳遞
class ProxyHttpClient() {
def get(url: String, proxy: ProxySettings,urlDownloaderConfig:
UrlDownloaderConfig)(implicit ec: ExecutionContext, system: ActorSystem, materializer: ActorMaterializer): Either[HttpError,
HttpSuccessResponse] = {???}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.