如何使用Reactive Extensions来限制客户端请求

时间:2014-09-22 15:06:11

标签: c# .net system.reactive

我有一台服务器从许多客户端接收许多对象,并且每次收到一个对象时都会触发ObjectReceived事件,包括发送了什么的参数。

  

问题:有一个客户端在我的服务器上遇到请求,但我的服务器总是响应。

我想根据是谁来制定请求。例如,如果我在100秒内从100个不同的客户端收到100个请求,并且每个客户端都提出了不同的请求,我会回复每个提出请求的客户;但是如果我在1秒钟内从2个客户端收到100个请求,并且每个客户端已经完成相同的请求50次,我只回复两次,一次回到客户端A,一次回到客户端B.

在Rx中可以吗?

2 个答案:

答案 0 :(得分:2)

是的,一种方法是按客户端ID对请求进行分组,并有选择地应用限制。

说你有这样的事件:

public class MyEvent
{
    public int ClientId { get; set; }

    public override string ToString()
    {
        return ClientId.ToString();
    }
}

让我们设置慢速和快速客户端:

var slow = Observable.Interval(TimeSpan.FromSeconds(2))
                     .Select(_ => new MyEvent { ClientId = 1 });

var fast = Observable.Interval(TimeSpan.FromSeconds(0.5))
                     .Select(_ => new MyEvent { ClientId = 2 });    

var all = slow.Merge(fast);

现在选择性地节流:

var throttled = all.GroupBy(x => x.ClientId).Select(
    // apply the throttle here, this could even test the key
    // property to apply different throttles to different clients
    x => x.Throttle(TimeSpan.FromSeconds(1)))
    .SelectMany(x => x);

测试一下:

throttled.Subscribe(x => Console.WriteLine(x.ToString())); 

有了这个节流,快速客户端将永远不会得到响应 - Throttle将无限期地抑制他的请求,因为它们距离不到一秒钟。您可以使用其他运算符以不同方式抑制 - 例如Sample可以在给定的时间间隔内选择一个请求。

编辑问题后

您可以应用不同于ClientId的规则并使用Throttle - 您可以在客户端流上使用DistinctUntilChanged()来清除重复请求,例如。

答案 1 :(得分:0)

略有不同的问题:Best way to implement request throttling in ASP.NET MVC?

在任何情况下,执行得非常好的典型算法都是:Hierarchical Token bucket

  

分层令牌桶(HTB)是更快的替代品   Linux中基于类的排队(CBQ)排队规则。

     

HTB有助于控制给定的出站带宽的使用   链接。 HTB允许使用单个物理链路来模拟多个   较慢的链接和不同的发送不同类型的流量   模拟链接。在这两种情况下,都必须指定如何划分   物理链接到模拟链接以及如何决定哪个模拟   链接一个给定的数据包将被发送。

     

换句话说,HTB对限制客户端的下载/上传非常有用   率。因此,有限的客户端无法使总带宽饱和。