包装速率限制API调用

Sup*_*JMN 4 .net c# concurrency asynchronous system.reactive

我有一个API调用,它接受每秒最大调用率.如果超过速率,则抛出异常.

我想把这个调用包装成一个抽象,它可以使调用率保持在极限之下.它将像网络路由器一样:处理多个呼叫并将结果返回给正确的呼叫者,关注呼叫率.目标是使调用代码尽可能不知道该限制.否则,具有此调用的代码中的每个部分都必须包装到try-catch中!

例如:想象一下,您可以从可以添加2个数字的extern API调用方法.此API可以每秒调用5次.高于此值的任何内容都将导致异常.

为了说明问题,限制通话费率的外部服务就像这个问题的答案中的那个

如何使用Observables构建速率限制API?

附加信息:

由于每次从代码的任何部分调用此方法时都不希望担心该限制,因此您可以考虑设计一个可以调用的包装器方法,而不必担心速率限制.在内部你关心限制,但在外面你暴露了一个简单的异步方法.

它类似于Web服务器.它如何将正确的结果包返回给正确的客户?

多个呼叫者将调用此方法,他们将在结果出现时获得结果.这种抽象应该像代理一样.

我怎么能这样做?

我确信包装方法的公司应该是这样的

public async Task<Results> MyMethod()
Run Code Online (Sandbox Code Playgroud)

在方法内部,它将执行逻辑,可能使用Reactive Extensions(Buffer).我不知道.

但是怎么样?我的意思是,多次调用此方法应该将结果返回给正确的调用者.这甚至可能吗?

非常感谢!

Aar*_*ron 6

有速率限制库可用(参见Esendex的TokenBucket GithubNuget).

用法非常简单,此示例将轮询限制为1秒

// Create a token bucket with a capacity of 1 token that refills at a fixed interval of 1 token/sec.
ITokenBucket bucket = TokenBuckets.Construct()
  .WithCapacity(1)
  .WithFixedIntervalRefillStrategy(1, TimeSpan.FromSeconds(1))
  .Build();

// ...

while (true)
{
  // Consume a token from the token bucket.  If a token is not available this method will block until
  // the refill strategy adds one to the bucket.
  bucket.Consume(1);

  Poll();
}
Run Code Online (Sandbox Code Playgroud)

我还需要让它为我的项目异步,我只是做了一个扩展方法:

public static class TokenBucketExtensions
{
    public static Task ConsumeAsync(this ITokenBucket tokenBucket)
    {
        return Task.Factory.StartNew(tokenBucket.Consume);
    }
}
Run Code Online (Sandbox Code Playgroud)

使用它你不需要抛出/捕获异常,编写包装器变得相当简单

  • 仅供参考 - 我已经分叉并重新发布了 TokenBucket,现在支持 .NET Standard 2.0 和 .NET 5.0 [此处](https://www.nuget.org/packages/CasCap.Apis.TokenBucket)。 (2认同)