【问题标题】:Play WS API: throttling request ratesPlay WS API:限制请求率
【发布时间】:2016-05-16 16:54:30
【问题描述】:

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

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

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

【问题讨论】:

  • 什么版本的 Play?
  • 播放版本 2.5.3

标签: scala web-services playframework playframework-2.0


【解决方案1】:

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

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

在 Play 2.5.x 中,我们可以按顺序处理这些,并使用akka.pattern.after 在每次调用之间强制异步延迟。我们flatMapFuture 的 web 服务调用结果将在一秒钟后返回 same 值。

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))
  }
}

【讨论】:

    【解决方案2】:

    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),但不确定它是否仍然有效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-09-03
      • 1970-01-01
      • 2018-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多