我有一个服务器,它从许多客户端接收许多对象,每次接收对象时都会触发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在限制客户端的下载/上传方面非常有用速度因此,有限的客户端不能使总带宽饱和。