繁体   English   中英

Lagom。 限制外部服务

[英]Lagom. Throttling for external service

我正在玩Lagom,它看起来不错,但我完全迷失了一个问题。

让我说我依赖外部HTTP服务,它只允许10个请求/秒,在其他情况下甚至可以禁止:)我googled,但没有找到任何工作的例子。 我可以在无类型的actor中包装服务并为其添加速率限制器,但我不明白如何在Akka Typed或Lagom服务之上实现它。

也许有人已经解决了这个问题? 谢谢!

你想要一个令牌桶 Akka-Streams内置Flow.throttle,但听起来你正在使用原始akka,所以不能使用它。 在Akka中存在令牌桶实现,但遗憾的是它没有提供任何使用指导,我自己也没有使用它。

对于我自己的用例(不是Akka而是使用Scala Futures),我编写了自己的令牌桶。 它允许我根据指定的限制引用Future的触发。 它是针对monix调度程序编码的,但是为了这个目的,它与Akka调度非常相似:

import java.util.concurrent.ConcurrentLinkedQueue

import monix.execution.Scheduler.Implicits.global
import monix.execution.atomic.AtomicInt

import scala.concurrent.{Future, Promise}
import scala.concurrent.duration._

case class RateLimiter(duration: FiniteDuration, maxInvocations: Int) {

  @volatile var permits: Int = maxInvocations
  val queue = new ConcurrentLinkedQueue[() => Any]()

  global.scheduleAtFixedRate(duration, duration) {
    this synchronized {
      permits = maxInvocations

      while (!queue.isEmpty && permits > 0) {
        Option(queue.poll()).foreach { fun =>
          permits -= 1
          fun.apply()
        }
      }
    }
  }

  def apply[T](f: => Future[T]): Future[T] =
    this synchronized {
      if (permits > 0) {
        permits -= 1
        f
      } else {
        val res = Promise[T]()
        queue.add(() => { res.completeWith(f) })
        res.future
      }
    }
}

用法是

val limiter = RateLimiter(1.second, 10)

limiter {
  someWebService.asyncCall()
}

暂无
暂无

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

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