如何使用反应式扩展来抑制客户端请求



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

问题:有一个客户端用请求惹恼了我的服务器,但我的服务器总是响应。

我想根据谁提出了请求来限制请求。例如,如果我在1秒内收到100个来自100个不同客户的请求,而每个客户都提出了不同的请求,我会回复每个提出请求的客户;但是,如果我在1秒内收到来自2个客户端的100个请求,并且每个客户端都做了50次相同的请求,我只响应两次,一次对客户端A,一次给客户端B。

在Rx中可能吗?

是的,一种方法是按客户端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())); 

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

编辑问题后

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

稍有不同的问题:在ASP.NET MVC中实现请求节流的最佳方式?

在任何情况下,表现非常好的典型算法都是:分层令牌桶。

分层令牌桶(HTB)是对Linux中基于类的排队(CBQ)排队规则。

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

换句话说,HTB在限制客户端的下载/上传方面非常有用速度因此,有限的客户端不能使总带宽饱和。

相关内容

  • 没有找到相关文章

最新更新