繁体   English   中英

如何使用Akka-Http进行并行Http请求?

[英]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**
  1. 我是否应该在这里使用actor而不是actorsystem并为其专门分配一个调度程序?

  2. 由于我持有的是二进制图像,因此在达到其目的后,我必须注意将其从内存中删除吗?

代码段将更有用。 提前致谢

我尝试遵循人们建议使用的在线建议

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM