gpt4 book ai didi

java - 为什么 Guava RateLimiter 不再限制每秒太大的许可数?

转载 作者:行者123 更新时间:2023-11-30 10:11:03 25 4
gpt4 key购买 nike

我正在使用一些 HTTP 库将一些数据上传到一些网络服务,并且需要限制每秒上传的数据量。使用的限制器是Guava RateLimiter ,几乎遵循限制某些数据流的第二个示例。对我来说有两个区别:我正在向消费者提供一些 InputStream 并在 read 中使用 aquire -一次只提供一个字节的方法。没有不同大小的数据包或类似的数据包,根据我的理解,这应该会让事情变得更容易。此外,我的每秒许可数大于示例。

对于低数字,事情似乎运作良好,但对于更高数字则不然,而且恰好有一个数字开始不再起作用。我在 KiB/s 方面进行了限制,并且包括 1 * 1024 * 976 在内的所有内容都有效,但是 977 事情开始失败并且限制没有似乎不再适用。使用一些网络监视器可以很容易地看到这一点,第一个配置限制上传 ~7-8 MBit/s,而后者提高到 60 或更多,具体取决于传出接口(interface)的使用方式等。据我了解,上传量的增加应该小得多,仅为 1 KiB/s,因此根本不显着。

我可以使用以下代码重现该问题:

import com.google.common.util.concurrent.RateLimiter;

public class Test
{
public static void main(String[] args)
{
RateLimiter rateLimiter = RateLimiter.create(1 * 1024 * 976);
RateLimiter msgLimiter = RateLimiter.create(1);
long aquired = 0L;

while (true)
{
rateLimiter.acquire();
++aquired;

if (msgLimiter.tryAcquire())
{
System.out.println(
String.format( "Aquired: %d MBit/s",
(aquired * 8) / (1024 * 1024)));
aquired = 0;
}
}
}
}

976 的结果:

Aquired: 0 MBit/s
Aquired: 7 MBit/s
Aquired: 7 MBit/s
Aquired: 7 MBit/s
Aquired: 7 MBit/s

977 的结果:

Aquired: 0 MBit/s
Aquired: 77 MBit/s
Aquired: 85 MBit/s
Aquired: 82 MBit/s
Aquired: 83 MBit/s

你知道为什么会这样吗?谢谢!

我已经读过 RateLimiter 关于 bursts 的“缺点”等等,但不知道这是否以及如何解释我的问题。

使用 TimedSemaphore 不会出现此问题:

import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.concurrent.TimedSemaphore;

import com.google.common.util.concurrent.RateLimiter;

public class Test
{
public static void main(String[] args) throws InterruptedException
{
int rateLimit = 1 * 1024 * 2000;
//RateLimiter rateLimiter = RateLimiter.create(rateLimit);
TimedSemaphore rateLimiter = new TimedSemaphore(1, TimeUnit.SECONDS, rateLimit);
RateLimiter msgLimiter = RateLimiter.create(1);
long aquired = 0L;

while (true)
{
rateLimiter.acquire();
++aquired;

if (msgLimiter.tryAcquire())
{
System.out.println(
String.format( "Aquired: %d MBit/s",
(aquired * 8) / (1024 * 1024)));
aquired = 0;
}
}
}
}

976 的结果与之前相同,因此值越大越有意义:

Aquired: 0 MBit/s
Aquired: 15 MBit/s
Aquired: 15 MBit/s
Aquired: 15 MBit/s
Aquired: 15 MBit/s

最佳答案

Guava RateLimiter 似乎只能工作到每秒 1,000,000 次请求调用的限制。如果您尝试每秒执行 1,000,001 次 aquire 调用,则对 aquire 的调用根本不会等待(aquire() 的返回值始终为 0.0)-> 不会发生限制。

因此,以下场景按预期工作:

RateLimiter.create(1000000l);//这将在使用 aquire()/aquire(1)

时起作用

RateLimiter.create(100000000l);//这将在使用 aquire(100) 或更高版本时起作用。

假设典型的网络流量永远不会逐字节接收,而是以 100-1000 字节的 block 为单位,Guava RateLimiter 的工作上限为每 100,000,000(~762 MBit)到 1,000,000,000(7.45 GBit/s)字节第二。

如果这些值对您的项目来说足够了,您可以坚持使用 Guava RateLimiter。如果不是,我建议改用 Apache TimedSemaphore。

关于java - 为什么 Guava RateLimiter 不再限制每秒太大的许可数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52611148/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com