Play WS API:限制请求率 [英] Play WS API: throttling request rates
问题描述
我正在使用异步 Play WS Scala API 来查询 RESTful 服务.我想知道如何处理包含要通过 WSClient
调用的请求 URL 的 List
,但每秒不超过一个请求(该服务允许每秒仅"1 个请求每个客户).从逻辑的角度来看,这个想法是从列表中获取一个元素 (URL),发出请求,然后在继续处理列表中的下一个元素之前等待一段时间.
I'm using the async Play WS Scala API to query a RESTful service. I wonder how I could process a List
containing request URLs to be called via WSClient
, but not more than one request per second (the service allows "only" 1 request per second per client). From a logical standpoint, the idea is to get an element (URL) from the list, make a request, then wait a certain amount of time before proceeding with the next element in the list.
- 在像 Play 这样的非阻塞和异步框架中使用旧的
Thread.sleep
当然是一个坏主意. - 对于
ScheduledThreadPoolExecutor
或其他需要生成新线程的方法,情况可能也是如此.
- using good old
Thread.sleep
in a non-blocking and asynchronous framework like Play is certainly a bad idea. - the same is probably true for things like
ScheduledThreadPoolExecutor
or other methods that require to spawn new threads.
如何在不对 Play 的异步和尽可能少线程"性质产生负面影响的情况下限制请求率?
How could I throttle the request rate without having a negative impact on the asynchronous and "as-less-threads-as-possible" nature of Play?
推荐答案
假设您有一个要获取的 URL 列表:
Suppose you have a list of URLs you watch to fetch:
val urls = List(
"http://www.google.com",
"http://stackoverflow.com",
"http://www.bing.com"
)
在 Play 2.5.x 中,我们可以顺序处理这些,并使用 akka.pattern.after
在每次调用之间强制异步延迟.我们flatMap
webservice 调用的Future
结果,在一秒后返回相同值.
In Play 2.5.x, we can process these sequentially, and use akka.pattern.after
to force an asynchronous delay between each call. We flatMap
the Future
result of a webservice call to something that will return the same value after one second.
Future.traverse(urls) { url =>
wsClient.url(url).get().flatMap { result =>
// potentially process `result` here
akka.pattern.after(1.second, actorSystem.scheduler)(Future.successful(result))
}
} // returns Future[List[WSResponse]]
这要求您有一个 WSClient
和 ActorSystem
组件可用,以及在隐式 ExecutionContext
范围内.
This requires that you have a WSClient
and ActorSystem
component available, as well as in implicit ExecutionContext
in scope.
在 Play 2.4.x 及更早版本中,您可以使用 Promise.timeout
执行相同操作:
In Play 2.4.x and earlier, you could do the same using Promise.timeout
:
Future.traverse(urls) { url =>
wsClient.url(url).get().flatMap { result =>
// potentially process `result` here
Promise.timeout(result, 1.second)
akka.pattern.after(1.second, actorSystem.scheduler)(Future.successful(result))
}
}
这篇关于Play WS API:限制请求率的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!