Scala 拉贡。外部服务的节流

Scala 拉贡。外部服务的节流,scala,lagom,akka-typed,Scala,Lagom,Akka Typed,我和拉格姆一起踢球,看起来不错,但有一个问题我完全输了 假设我依赖于外部HTTP服务,它只允许每秒10个请求,在其他情况下甚至可以禁止:) 我在谷歌上搜索过,但没有找到任何有效的例子。我可以用非类型化的actor包装服务并为其添加速率限制,但我不知道如何在Akka类型或Lagom服务之上实现它 也许有人已经解决了这样的任务?谢谢 你想要一份工作。Akka Streams内置了此功能,但听起来您使用的是原始Akka,所以不能使用它。有一个,但不幸的是,它没有提供任何使用指南,我自己也没有使用过 对

我和拉格姆一起踢球,看起来不错,但有一个问题我完全输了

假设我依赖于外部HTTP服务,它只允许每秒10个请求,在其他情况下甚至可以禁止:) 我在谷歌上搜索过,但没有找到任何有效的例子。我可以用非类型化的actor包装服务并为其添加速率限制,但我不知道如何在Akka类型或Lagom服务之上实现它

也许有人已经解决了这样的任务?谢谢

你想要一份工作。Akka Streams内置了此功能,但听起来您使用的是原始Akka,所以不能使用它。有一个,但不幸的是,它没有提供任何使用指南,我自己也没有使用过

对于我自己的用例(不是Akka,而是使用Scala Futures),我编写了自己的令牌桶。它允许我参考基于指定限制的未来触发。它是针对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()
}
你想要一个。Akka Streams内置了此功能,但听起来您使用的是原始Akka,所以不能使用它。有一个,但不幸的是,它没有提供任何使用指南,我自己也没有使用过

对于我自己的用例(不是Akka,而是使用Scala Futures),我编写了自己的令牌桶。它允许我参考基于指定限制的未来触发。它是针对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()
}

谢谢,格罗斯。这是可怕的,但我认为它应该是一些标准的解决方案在拉各姆这样的基本任务。我只是好奇,因为我没有在谷歌上搜索任何东西,比如anks,Grogs,这是一个很好的模板,可以理解如何在多个缩放节点中实现这一点。谢谢,格罗斯。这是可怕的,但我认为它应该是一些标准的解决方案在拉各姆这样的基本任务。我只是好奇,因为我没有在谷歌上搜索任何东西,比如anks,Grogs,这是一个很好的模板,可以理解如何在多个缩放节点中实现这一点。我希望将来能解决这个问题,我希望将来能解决这个问题。