使用延迟请求限制的缺点是什么(C# .Net 4 Web 服务器)



我们正在运行一个 Http API,并希望能够对用户每个时间单位可以执行的请求数设置限制。达到此限制后,我们不希望用户收到错误,例如 Http 429。相反,我们希望增加响应时间。这样做的结果是,用户可以继续工作,但速度较慢,然后可以选择升级或不升级其付费计划。这个解决方案可以很容易地使用 Thread.sleep(或类似的东西(实现 x 秒数,对超过其限制的用户的所有请求。

我们认为,在最坏的情况下,单个服务器的可能连接数可能存在问题,因为只要我们继续延迟响应,我们就会保持连接打开,从而限制可能的其他连接的数量。

对 API 的所有请求都在异步运行。服务器本身构建为可扩展,并在负载平衡器后面运行。如有必要,我们可以启动其他服务器。

在搜索这种类型的限制时,我们发现这种限制用户的方式的例子很少,我们发现的例子似乎根本不关心连接耗尽。所以我们想知道这不是问题吗?

我们是否缺少任何缺点,或者这是一个可行的解决方案?我们可以同时打开多少个连接而不会开始出现问题?我们的愿景可以用另一种方式解决,即不给用户带来错误吗?

Thread.Sleep()几乎

是你在Web服务器上能做的最糟糕的事情。异步运行并不重要,因为这仅适用于 I/O 绑定操作,然后释放线程以执行更多工作。

通过使用 Sleep() 命令,您将有效地使该线程在休眠期间停止运行。

ASP.Net 应用程序池可用的线程数量有限,因此在最坏的情况下,如果所有连接同时处于休眠状态,则与服务器的连接总数将达到 40-50(无论默认值是什么(。

其次

这在DOS方面开辟了一个主要的攻击媒介。如果我是攻击者,我可以通过启动 100 或 1000 个连接来轻松干掉您的整个服务器,所有这些都使用相同的 API 密钥。使用这种方法,服务器将尽职尽责地开始将所有线程置于睡眠状态,然后游戏结束。

更新

因此,您可以使用Task.Delay()在响应中插入任意数量的延迟。在引擎盖下,它使用比使用螺纹轻得多的Timer

await Task.Delay(numberOfMilliseconds);

然而。。。

这只照顾了等式的一面。在延迟期间,您仍然与服务器有打开的连接。因为这是一个有限的资源,它仍然让你容易受到通常不存在的DOS攻击。

这对您来说可能是一个可以接受的风险,但您至少应该意识到这种可能性。

为什么不简单地添加一个"请稍候..."在客户端上人为地看起来像是在处理? 在服务器上添加人为延迟会花费您,它会不必要地占用连接和线程。