Java 发送多个请求时的Akka BufferOverflowException

Java 发送多个请求时的Akka BufferOverflowException,java,scala,akka,future,akka-http,Java,Scala,Akka,Future,Akka Http,这是我的密码 Future.sequence((2 to firstPage.pages).map { count => getCommentPage(av, count) }).map(//do something) 在getCommentPage中,一个Http().singleRequest用于获取数据,如下所示: val responseFuture: Future[HttpResponse] = Http(system).singleRequest(HttpRe

这是我的密码

Future.sequence((2 to firstPage.pages).map
{ count =>
    getCommentPage(av, count)
}).map(//do something)
getCommentPage
中,一个
Http().singleRequest
用于获取数据,如下所示:

val responseFuture: Future[HttpResponse] =
    Http(system).singleRequest(HttpRequest(GET, uri = requestUri))
responseFuture
    .map(_.entity)
    .flatMap(_.toStrict(10 seconds)(materializer))
    .map(_.data)
    .map(_.utf8String)
    .map((jsonString: String) => {
        //do something to extract data
    }
val poolClientFlow =
    Http().cachedHostConnectionPool[HttpRequest](host, port)

def performRequest(request: HttpRequest): Future[HttpResponse] =
    Source
      .single(request)
      .via(poolClientFlow)
      .mapAsync(1) {
        case (response, _) =>
          Future.fromTry(response)
      }
      .runWith(Sink.head)
小的
firstPage.pages
可以正常工作,但是当
firstPage.pages
很大(大约50页或更大)时,会有一个例外:

akka.stream.BufferOverflowException: Exceeded configured max-open-requests value of [32]. This means that the request queue of this pool (HostConnectionPoolSetup(api.bilibili.cn,80,ConnectionPoolSetup(ConnectionPoolSettings(4,0,5,32,1,30 seconds,ClientConnectionSettings(Some(User-Agent: akka-http/10.0.9),10 seconds,1 minute,512,None,<function0>,List(),ParserSettings(2048,16,64,64,8192,64,8388608,256,1048576,Strict,RFC6265,true,Full,Error,Map(If-Range -> 0, If-Modified-Since -> 0, If-Unmodified-Since -> 0, default -> 12, Content-MD5 -> 0, Date -> 0, If-Match -> 0, If-None-Match -> 0, User-Agent -> 32),false,akka.stream.impl.ConstantFun$$$Lambda$244/19208387@4780bf,akka.stream.impl.ConstantFun$$$Lambda$244/19208387@4780bf,akka.stream.impl.ConstantFun$$$Lambda$245/6903324@1d25a2e),None),TCPTransport),akka.http.scaladsl.HttpConnectionContext$@796a3e,akka.event.MarkerLoggingAdapter@1cc552a))) has completely filled up because the pool currently does not process requests fast enough to handle the incoming request load. Please retry the request later. See http://doc.akka.io/docs/akka-http/current/scala/http/client-side/pool-overflow.html for more information.
akka.stream.BufferOverflowException:超出配置的最大打开请求值[32]。这意味着此池的请求队列(HostConnectionPoolSetup(api.bilibili.cn,80,ConnectionPoolSetup)(ConnectionPoolSettings(4,0,5,32,1,30秒,ClientConnectionSettings)(一些(用户代理:akka http/10.0.9)),10秒,1分钟,512,无,列表(),ParserSettings(2048,16,64,648192,6483886082561048561048576,严格,RFC6265,true,Full,Error,Map(如果范围->0,如果自->0修改,如果自->0未修改,默认->12,Content-MD5->0,日期->0,如果匹配->0,如果不匹配->0,用户代理->32),false,akka.stream.impl.ConstantFun$$Lambda$244/19208387@4780bf,akka.stream.impl.ConstantFun$$$$Lambda$244/19208387@4780bf,akka.stream.impl.ConstantFun$$$$Lambda$245/6903324@1d25a2e),无),tcpttransport),akka.http.scaladsl.HttpConnectionContext$@796a3e,akka.event。MarkerLoggingAdapter@1cc552a)))已完全填满,因为池当前处理请求的速度不够快,无法处理传入的请求负载。请稍后重试该请求。请参阅http://doc.akka.io/docs/akka-http/current/scala/http/client-side/pool-overflow.html 了解更多信息。

如何解决此问题?

为什么不在错误消息中转到网站


您需要使用
akka.http.host connection pool.max connections
配置application.conf,并将数字从32增加到更高的数字。

为什么不在错误消息中转到网站


您需要使用
akka.http.host connection pool.max connections
配置application.conf,并将数字从32增加到一个更高的数字。

您要寻找的东西是专用的 简化后的代码如下所示:

val responseFuture: Future[HttpResponse] =
    Http(system).singleRequest(HttpRequest(GET, uri = requestUri))
responseFuture
    .map(_.entity)
    .flatMap(_.toStrict(10 seconds)(materializer))
    .map(_.data)
    .map(_.utf8String)
    .map((jsonString: String) => {
        //do something to extract data
    }
val poolClientFlow =
    Http().cachedHostConnectionPool[HttpRequest](host, port)

def performRequest(request: HttpRequest): Future[HttpResponse] =
    Source
      .single(request)
      .via(poolClientFlow)
      .mapAsync(1) {
        case (response, _) =>
          Future.fromTry(response)
      }
      .runWith(Sink.head)
一定要打电话

response.discardEntityBytes()
或者只是将其解组以防止资源泄漏


他们在文档中警告说这是一个反模式,但如果您有足够的内存并且不需要任何队列管理,它实际上运行得很好。

您正在寻找的东西是专用的 简化后的代码如下所示:

val responseFuture: Future[HttpResponse] =
    Http(system).singleRequest(HttpRequest(GET, uri = requestUri))
responseFuture
    .map(_.entity)
    .flatMap(_.toStrict(10 seconds)(materializer))
    .map(_.data)
    .map(_.utf8String)
    .map((jsonString: String) => {
        //do something to extract data
    }
val poolClientFlow =
    Http().cachedHostConnectionPool[HttpRequest](host, port)

def performRequest(request: HttpRequest): Future[HttpResponse] =
    Source
      .single(request)
      .via(poolClientFlow)
      .mapAsync(1) {
        case (response, _) =>
          Future.fromTry(response)
      }
      .runWith(Sink.head)
一定要打电话

response.discardEntityBytes()
或者只是将其解组以防止资源泄漏


他们在文档中警告说这是一个反模式,但如果您有足够的内存并且不需要任何队列管理,它实际上运行良好。

您可以尝试类似的方法

 val result = Source(1 to 10).mapAsyncUnordered(parallelism = 5) { count =>
    getCommentPage(av, count)
 }.runWith(Sink.seq)

请注意,并行度值应小于akka.http.host connection pool.max connections

您可以尝试以下操作

 val result = Source(1 to 10).mapAsyncUnordered(parallelism = 5) { count =>
    getCommentPage(av, count)
 }.runWith(Sink.seq)

请注意,并行度值应该小于
akka.http.host connection pool.max connections

我不认为更改配置是解决此问题的好方法。同时使用太多http连接并不好。实际上,我想找到一种类似http queue的方法来解决此问题。似乎
Flow
是解决此问题的一种强大方法我有它,但我不知道如何使用它。即使我更改了
最大连接数
,这也不应该起作用,因为
页面
可能非常大。我不认为更改配置是解决这一问题的好方法。同时更改太多HTTP连接并不好。实际上,我想找到一种类似HTTP队列的方法来解决这一问题。Seems认为
Flow
是解决它的一个强大方法,但我不知道如何使用它。即使我更改
max connections
,这也不应该起作用,因为
页面可能非常非常大这是我想要的!但是
源(请求)
(其中
请求
索引eq[(HttpRequest,Int)]
)而不是
源代码。单个
更好?这取决于您的需要。即使您从不同的线程调用
performRequest
,它们也会通过连接池排队。不,这实际上不是一个好主意。这可能会遇到相同的错误,并且性能不如您的原始代码。请参阅d中的注释获取更多信息的文档。这是我想要的!但它是
源(请求)
(其中
请求
索引eq[(HttpRequest,Int)]
)而不是
源代码。单个
更好?这取决于您的需要。即使您从不同的线程调用
performRequest
,它们也会通过连接池排队。不,这实际上不是一个好主意。这可能会遇到相同的错误,并且性能不如您的原始代码。请参阅d中的注释有关更多信息,请参阅文档。