如何在 Scala 的循环中限制函数调用的速率 [英] How to rate limit function call in a loop in Scala

查看:30
本文介绍了如何在 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)

推荐答案

您可以使用 阿卡节流阀.Link2

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆