Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用可观测数据构建速率限制API?_C#_.net_Async Await_System.reactive_Rate Limiting - Fatal编程技术网

C# 如何使用可观测数据构建速率限制API?

C# 如何使用可观测数据构建速率限制API?,c#,.net,async-await,system.reactive,rate-limiting,C#,.net,Async Await,System.reactive,Rate Limiting,我想创建一个简单的计算器服务,它有一个单一的方法来添加数字。这个Add方法应该是async,并且必须限制在给定时间进行的并发调用的数量。例如,每秒并发调用不超过5次。如果超过速率限制,调用将引发异常 课程应该是这样的: public class RateLimitingCalculator { public async Task<int> Add(int a, int b) { //... } } 公共类费率限制计算器 { 公共异步任务添加

我想创建一个简单的计算器服务,它有一个单一的方法来添加数字。这个
Add
方法应该是
async
,并且必须限制在给定时间进行的并发调用的数量。例如,每秒并发调用不超过5次。如果超过速率限制,调用将引发异常

课程应该是这样的:

public class RateLimitingCalculator
{
    public async Task<int> Add(int a, int b) 
    {
        //...
    }
}
公共类费率限制计算器
{
公共异步任务添加(int a、int b)
{
//...
}
}

有什么想法吗?我想用反应式扩展实现它,但如果使用另一种策略更好,我会坚持下去

我认为在这里使用Rx没有意义,除非您可以将您的方法重写为类似于
public IObservable Add(IObservable values)
,正如Enigmativity在评论中所建议的那样

我要做的是将利率限制问题分为一个单独的类别。这样,您的代码可以如下所示:

public class RateLimitingCalculator
{
    private RateLimiter rateLimiter = new RateLimiter(5, TimeSpan.FromSeconds(1));

    public async Task<int> Add(int a, int b) 
    {
        rateLimiter.ThrowIfRateExceeded();

        //...
    }
}
class RateLimiter
{
    private readonly int rate;
    private readonly TimeSpan perTime;

    private DateTime secondStart = DateTime.MinValue;
    private int count = 0;

    public RateLimiter(int rate, TimeSpan perTime)
    {
        this.rate = rate;
        this.perTime = perTime;
    }

    public void ThrowIfRateExceeded()
    {
        var now = DateTime.UtcNow;

        if (now - secondStart > perTime)
        {
            secondStart = now;
            count = 1;
            return;
        }

        if (count >= rate)
            throw new RateLimitExceededException();

        count++;
    }
}

有些想法可能会对你有所帮助。你真的应该避免混合单子。我认为如果你有这样一个签名,就更容易解释清楚了:
public-IObservable-Add(IObservable-values)
@Enigmativity“避免混合monad”是什么意思?另外,您认为使用Rx对API进行速率限制有意义吗?@SuperJMN-
IObservable
Task
都是单子。它们是“超级类型”,接受底层的
T
,并赋予其超级能力。如果你呆在你的单子里,那么一切都很好,但是如果你在两个单子之间走,那么你可能会出错。所以我会避免尝试使用一个单子(Rx)来限制另一个(TPL)。请继续使用Rx,它拥有速率限制所需的所有运算符。每秒不超过5个并发调用我还希望以尽可能透明的方式使用速率限制API来执行相反的操作:。也许你能帮忙。非常感谢!我更喜欢使用
秒表
而不是
DateTime.UtcNow
来测量时间间隔。它更轻,并保证始终向前推进。
DateTime.UtcNow
会根据系统进行调整,因此可以向后移动。