Guava之RateLimiter的设计

Posted Jenkov

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Guava之RateLimiter的设计相关的知识,希望对你有一定的参考价值。

Guava源码中很详尽的解释了RateLimiter的设计。

从概念上看,限流器以配置速率释放允许的请求(permit)。如有必要,调用acquire()将会阻塞知道一个允许可用。一旦被获取(acquired),允许(permits)将不必释放。

限流器在并发环境中是安全的:它限制所有线程总的调用速率。但是,值得注意的是,它难以保证公平。
限流器经常被用来限制一些物理或逻辑资源被访问的速率。经常和它对比的是j.u.c.Semaphore,它限制了访问资源总的并发数。(并发数和速率紧密相关,参见Little‘s Law)

限流器原始定义为许可被发布的速率。没有多余的配置,许可将被以固定速率(——字面意义被定义为 许可/sec) 分发。通过调节独立的许可之间的延迟,保证许可按照配置的速率平滑分发。

在限流器正式进入稳定速率前,通常允许限流器有一个短暂的预热阶段。在该阶段,许可分发速率稳步提升,直至预定到达速率为止。

举例,想象我们有一组任务要执行,但我们不想要每秒提交超过2个任务。

  final RateLimiter rateLimiter = RateLimiter.create(2.0); // rate is 2 permits per second"
  void submitTasks(List<Runnable> tasks, Executor executor) {
    for (Runnable task : tasks) {
      rateLimiter.acquire(); // may wait
      executor.execute(task);
    }
  }

另一个例子是,想象我们生产一组数据流,但是我们想以5kb/sec速率恒定接收它。这个想法可以以限流器方式实现。即,每个许可对应一个字节,指定(限流器)恒定的速率为每秒5000次许可。

final RateLimiter rateLimiter = RateLimiter.create(5000.0); // rate = 5000 permits per second
   void submitPacket(byte[] packet) {
     rateLimiter.acquire(packet.length);
     networkService.send(packet);
   }

注意,请求的许可数量不会影响到对请求本身的压制。(acquire(1)会和acquire(1000)产生相同的效果),但是它会影响到对下一个请求的压制作用。如果成本较大的任务在空闲时到达限流器,将会被立即允许。但这之后的请求将会遭受额外的限制,为上次高昂代价的任务买单。

以上是关于Guava之RateLimiter的设计的主要内容,如果未能解决你的问题,请参考以下文章

Guava RateLimiter限流器使用示例

Guava RateLimiter限流问题

#私藏项目实操分享#Java技术开发专题系列之Guava RateLimiter针对于限流器的入门到实战(含源码分析介绍)

Guava官方文档-RateLimiter类

使用Guava RateLimiter限流

Guava RateLimiter详解以及源码分析