假设我们有从Future[T]
返回CompletableFuture[T]
或java AsyncCompletionHandler[T]
或自定义org.asynchttpclient
的方法。我想限制对这种方法的所有调用。
你会怎么做?目前,我使用基于MergeHub.source
的{{1}}来汇总所有请求。问题我有
这是代码
Sink
换句话说,有多个地方,如主要的内容。所有这些都应该作为呼叫总和的限制。
答案 0 :(得分:1)
作为一般性评论,您可能没有MergeHub
步骤并简化您的管道。见下面的例子
object Main {
private implicit val system = ActorSystem("root")
private implicit val executor = system.dispatcher
private implicit val mat = ActorMaterializer(ActorMaterializerSettings(system))
def makeRequest(url: String): Future[Response] = {
val promise = Promise[Response]()
asyncHttpClient.prepareGet(url).execute(new AsyncCompletionHandler[Response] {
def onCompleted(response: Response) = {
promise.success(response)
response
}
override def onThrowable(t: Throwable) {
promise.failure(t)
super.onThrowable(t)
}
})
promise.future
}
val asyncHttpClient = new DefaultAsyncHttpClient()
def main(args: Array[String]): Unit = {
val start = ZonedDateTime.now()
println("Start!")
Source(1 to 20)
.throttle(1, FiniteDuration(2000, MILLISECONDS), 1, ThrottleMode.Shaping)
.mapAsync(4) { index =>
println(s"${ZonedDateTime.now().toEpochSecond - start.toEpochSecond} s - Requesting $index")
makeRequest(s"http://httpbin.org/get?param=$index").map { r =>
println(s"${ZonedDateTime.now().toEpochSecond - start.toEpochSecond} s - Got $index - Code ${r.getStatusCode}")
}
}
.runWith(Sink.ignore)
.onComplete {
case Success(_) =>
println(s"${ZonedDateTime.now().toEpochSecond - start.toEpochSecond} Done!")
asyncHttpClient.close()
system.terminate()
case Failure(ex) =>
ex.printStackTrace()
asyncHttpClient.close()
system.terminate()
}
Await.result(system.whenTerminated, Duration.Inf)
}
}
然而,在两种实现中,我都看到请求被正确限制 - 每2秒一次,大致从第二次〜0次到第二次~38次。
你能详细说明你对这里的期望吗?