如何使用响应式扩展来限制客户端请求

Posted

技术标签:

【中文标题】如何使用响应式扩展来限制客户端请求【英文标题】:How to use Reactive Extensions to throttle client requests 【发布时间】:2014-09-22 15:06:11 【问题描述】:

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

问题:有一个客户端向我的服务器发出请求,但我的服务器总是响应。

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

在 Rx 中可以吗?

【问题讨论】:

可能是。我们缺少一些信息。假设您想以 1 个请求/秒的速度响应,但烦人的客户端以 100 个/秒的速度发送它们。剩下的99个怎么办?排队?当队列有 1,000,000 个条目时会发生什么?内存不足?拒绝他们?如何拒绝? 你说得对,已编辑 您所面临的情况称为 DOS 攻击。安全性是您的应用程序的一个方面,在我看来,您应该在尽可能低的层中修复它。看看这个Prevent Malicious Requests - DOS Attacks 和Block DoS attacks easily in ASP.NET。还请查看最后一个链接的 cmets,以获取一些改进建议。 我当然同意最低级别的观点——也就是说,我必须制定政策来防止非恶意过度使用具有复杂业务领域规则的 API。不过,这些天来,这类东西越来越多地通过 API 托管产品(如 apigee、3scale 等)提供。甚至 Azure 现在也有。 【参考方案1】:

是的,一种方法是按客户端 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() 以清除重复请求。

【讨论】:

嗨,Throttle 和 Sample 实际上延迟了我订阅的执行。有没有办法立即响应第一个请求,并且在一定时间内不接受同一种请求? @sam 试试这个。我为这个老问题添加了一个新答案,我认为它可以很好地解决所有问题:***.com/questions/7999503/…【参考方案2】:

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

在任何情况下,性能非常好的典型算法都是:Hierarchical Token bucket。

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

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

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

【讨论】:

以上是关于如何使用响应式扩展来限制客户端请求的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Rx.Net 实现状态轮询?

如何使用 WebClient 反应式 Web 客户端发送带有 zip 正文的 POST 请求

Python请求库遇到重试限制时如何访问服务器响应

Nginx内容缓存

使用 css 限制响应式图像的高度

如何允许无限制的发布请求 expressjs