繁体   English   中英

播放WS API:限制请求率

[英]Play WS API: throttling request rates

我正在使用异步Play WS Scala API来查询RESTful服务。 我想知道如何处理包含要通过WSClient调用的请求URL的List ,但每秒不超过一个请求(该服务允许每个客户端每秒“仅”1个请求)。 从逻辑的角度来看,我们的想法是从列表中获取元素(URL),发出请求,然后等待一段时间再继续列表中的下一个元素。

  • 在像Play这样的非阻塞和异步框架中使用好的旧Thread.sleep肯定是一个坏主意。
  • 对于像ScheduledThreadPoolExecutor或其他需要生成新线程的方法,情况也是如此。

如何在不对Play的异步和“尽可能线程”性质产生负面影响的情况下限制请求率?

假设您有一个您要获取的URL列表:

val urls = List(
  "http://www.google.com",
  "http://stackoverflow.com",
  "http://www.bing.com"
)

在Play 2.5.x中,我们可以按顺序处理它们,并使用akka.pattern.after强制每次调用之间的异步延迟。 我们将Web服务调用的Future结果flatMap到一秒钟后将返回相同值的内容。

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]]

这要求您具有可用的WSClientActorSystem组件,以及范围中的隐式ExecutionContext


在Play 2.4.x及更早版本中,您可以使用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))
  }
}

Akka在这里有一个方便的调度程序功能: http//doc.akka.io/docs/akka/current/scala/scheduler.html

由于Akka已经在Play中,因此您无需导入任何其他内容。
它不会是最干净或容易测试的,但你可以这样:

val webserviceCall : Runnable = new Runnable {

    override def run(): Unit = {
        // do webservice call work
        // figure out if you need to make more webservice calls, and if you do:
        actorSystem.scheduler.scheduleOnce(0 seconds, 1 seconds, webserviceCall)
    }

}

actorSystem.scheduler.scheduleOnce(0 seconds, webserviceCall)

或者,您可以使用此人之前做过的这个Akka消息调节器: http//doc.akka.io/docs/akka/snapshot/contrib/throttle.html

我之前使用过它(我认为去年是Akka 2.3)但不确定它是否仍然有用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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