如何在 Scala 的循环中限制函数调用的速率 [英] How to rate limit function call in a loop in Scala
本文介绍了如何在 Scala 的循环中限制函数调用的速率的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
以下代码对外部 API 进行了大量调用.此 API 不允许每秒查询超过 3 次.syncCallToApi
是 api 客户端库提供的一个函数,用于执行同步请求并返回结果.
The following code do a bunch of calls to an external API. This API does not allow more than 3 queries per second. syncCallToApi
is a function provided by the api client library that do a synchronous request and returns the result.
在 Scala 中并发调用 callToApi
的最佳方式是每秒不超过 3 次,同时保持以下语义:
What is the best way in Scala to concurrently call callToApi
no more than 3 times per seconds while keeping the following semantics:
val ids = Seq(12980,2932,3441,42334,980,32,4531,7234)
val results: Seq[Item] = ids.map(id => syncCallToApi(id))
println(results)
推荐答案
import akka.actor.{Props, Actor, ActorSystem}
import akka.contrib.throttle.Throttler._
import akka.contrib.throttle.TimerBasedThrottler
import akka.util.Timeout
import java.util.concurrent.TimeUnit
import scala.concurrent.duration._
import akka.pattern.ask
import Api._
import scala.concurrent.{Await, ExecutionContext, Future}
import ExecutionContext.Implicits.global
object Main extends App {
implicit val timeout = Timeout(1 minute)
val system = ActorSystem("system")
val throttler = system.actorOf(Props(new TimerBasedThrottler(new Rate(3, Duration(1, TimeUnit.SECONDS)))))
val worker = system.actorOf(Props(classOf[ExternalApiActor]))
throttler ! SetTarget(Option(worker))
val ids = Seq(12980,2932,3441,42334,980,32,4531,7234)
val listOfFutures: Seq[Future[Item]] = ids.map { id =>
ask(throttler, id).mapTo[Item]
}
val futureList: Future[Seq[Item]] = Future.sequence(listOfFutures)
val results: Seq[Item] = Await.result(futureList, 1 minute)
println(results)
system.shutdown()
}
class ExternalApiActor extends Actor {
def receive = {
case id: Int => sender ! syncCallToApi(id)
}
}
object Api {
def syncCallToApi(number: Int): Item = {
println(s"call the API with $number")
Item(number)
}
}
case class Item(id: Int)
//build.sbt
scalaVersion := "2.10.1"
libraryDependencies += "com.typesafe.akka" % "akka-contrib_2.10" % "2.1.4"
这篇关于如何在 Scala 的循环中限制函数调用的速率的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文