【问题标题】:How to change the rate limit whilst using a RateGate?如何在使用 RateGate 时更改速率限制?
【发布时间】:2022-03-13 09:12:37
【问题描述】:

我正在使用简洁的RateGate class 来限制我发送到服务器的请求数。

我的代码如下所示:

var RateLimit = 35;

using(var RateGate = new RateGate(RateLimit, TimeSpan.FromSeconds(1)))
{
    for(var Run = 1; Run <= 50; Run++)
    {
        for(var Batch = 0; Batch < 200; Batch++)
        {
            // Do some work, then...

            MyClass MyClass;

            if(MyClass.RateLimitHit)
            {
                RateLimit--;
            }

            RateGate.WaitToProceed();
        }
    }
}

if(MyClass.RateLimitHit) 内部,我需要将速率限制降低1。不仅仅是变量RateLimit,而是实际RateGate 中运行的限制。

在 RateGate 类中,我看到了这个:

/// <summary>
/// Number of occurrences allowed per unit of time.
/// </summary>
public int Occurrences { get; private set; }

我的问题是:如果我将 private set; 更改为 set; 并在 RateLimit--; 之后添加 RateGate.Occurrences = RateLimit; 这会达到我想要的效果吗?

我试过了,但看起来RateGate 继续以 35/s 的最大速率执行。

【问题讨论】:

  • 澄清一下...为了赏金,您是在寻找修改后的 RateGate 类,还是从 RateGate 类继承和覆盖/扩展某些功能的新类?

标签: c# .net rate-limiting rategate


【解决方案1】:

我也想这样做,我通过反转时间和发生找到了一个很好的解决方案。 什么意思:

我没有将我的问题表达为“我希望每秒出现 N 次”,而是将其反转为“我希望每 1/N 秒出现 1 次”。这样,我可以轻松更改时间单位,而不是修改出现次数(始终为 1)。我在类中添加了这个方法(你也可以派生):

private object _updateTimeUnitLock = new object();
private int nextUpdateTime = 0;
public bool UpdateTimeUnit(TimeSpan timeUnit, TimeSpan dontUpdateBefore)
{
    lock (_updateTimeUnitLock)
    {
        if ((nextUpdateTime == 0) || (nextUpdateTime <= Environment.TickCount))
        {
            TimeUnitMilliseconds = (int)timeUnit.TotalMilliseconds;
            nextUpdateTime = Environment.TickCount + (int)dontUpdateBefore.TotalMilliseconds;

            return true;
        }

        return false;
    }
}

我的必须是线程安全的,并且我需要一种方法来防止在某些时间段内发生更改,所以在您这边,您可能想要移除锁和 dontUpdateBefore 参数,这意味着您可以只设置 TimeUnitMilliseconds 并且将选择该值在下一个计时器滴答声中。 现在,要调用它,您只需要根据您想要的出现次数来计算您想要的新时间。

希望它能满足您的需求。

22 年 3 月 12 日更新:RateGate 课程的原始链接已损坏,但我在Github 上找到了该课程的副本。

【讨论】:

  • 非常感谢 Nicolas 的回答,看起来很有希望!很快就会检查出来。
  • 这非常有效,非常感谢您将问题反转为每(1000 /(每秒数))毫秒出现 1 次的想法。最后,代码就变成了RateGate.TimeUnitMilliseconds = 1000 / 35;
  • 当然public int TimeUnitMilliseconds { get; private set; }也应该由private set;改为set;
【解决方案2】:

Occurrences 值作为最大计数传递给构造函数中的信号量,因此更改属性不会影响该实例的行为。

public RateGate(int occurrences, TimeSpan timeUnit)
{
    // Snipped all the code that doesn't pertain to this question...

    Occurrences = occurrences;

    // Create the semaphore, with the number of occurrences as the maximum count.
    _semaphore = new SemaphoreSlim(Occurrences, Occurrences);
}

看起来 Occurrences 更像是一个只读属性,可让您查看传入构造函数的内容。

【讨论】:

  • 感谢您解释为什么这不起作用 Jeff;我不认为您有任何想法我将如何更改最大速率限制,同时在执行 RateGate?
  • 我不确定目前的安排是否可行。如果我理解正确,该信号量正在控制事物的流动,因此如果您将其清除,它将重置状态。话虽如此,可以编写一个方法(或实现该集合),以便在创建新信号量时使用现有信号量的当前计数......类似于:_semaphore = new SemaphoreSlim(_semaphore.CurrentCount, newOccurrenceValue) 但我不能保证它的行为。
  • 我现在添加了赏金;也许你想试试这是否可能......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-24
  • 2013-11-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多