RateLimiter 的未来

Future with RateLimiter

假设我有一个像这样的简单阻塞 HTTP 客户端:

def httpGet(url: URL): Future[String] = ??? 

现在我想用httpGet来调用有请求速率限制的服务器;例如1000 requests/sec。由于标准库不提供速率限制器,我将使用 RateLimiter of Guava:

import com.google.common.util.concurrent.RateLimiter
import scala.concurrent.{ExecutionContext, Future, blocking}

def throttled[A](fut: => Future[A], rateLimiter: RateLimiter)
                (implicit ec: ExecutionContext): Future[A] = {
  Future(blocking(rateLimiter.acquire())).flatMap(_ => fut)
}

implicit val ec = ExecutionContext.global
val rateLimiter = RateLimiter.create(permitsPerSeconds = 1000.0)
val throttledFuture = throttled(httpGet(url), rateLimiter)

有意义吗?
您会使用另一个执行上下文来执行 rateLimiter.acquire() 吗?

既然你在 acquire 周围使用 blocking,没关系,IMO。

根据调用 httpGet 的线程中完成的工作量,如果您使用的是 Scala 2.13,可能值得考虑使用 parasitic 执行上下文。

样式 nit,但可能值得利用 Scala 的能力来使用 { 围绕单个参数列表:

def throttled[A](rateLimiter: RateLimiter)(fut: => Future[A])(implicit ec: ExecutionContext): Future[A]

val throttledFuture = throttled(rateLimiter) { httpGet(url) }