【问题标题】:How to rate limit per user?如何对每个用户进行速率限制?
【发布时间】:2019-12-30 15:19:39
【问题描述】:

我的应用程序具有基于信用的使用系统。但是,在我当前的结构中,如果用户在足够小的窗口中发出 2 个请求,他可以通过这两个请求,这会导致系统故障和用户的信用值负值,因为当第二个请求应该时,他的信用会减少两次'不被允许。

我想确保单个用户在给定时间只能运行一个请求,我尝试使用 express-rate-limit 但这不适合我的用例,因为这些请求是由谷歌云功能发出的已设置,而不是用户本人。

但是,我有特定的用户 ID 来标识这些请求,因此我可以拥有特定于用户 ID 的队列来逐一处理单个用户的请求。

这是否是解决信用使用问题的适当且可扩展的设计,还是有更好的替代方案?

【问题讨论】:

  • 考虑重新设计您的系统,以便没有时间限制但有资源限制,例如数据库约束或事件源。
  • 听起来你想要一个全局的test and set,因为请求可以并行执行。我猜测具有 ACID 属性的同步数据库。也许是单节点 Cloud SQL,或者如果您有容量,那么 Cloud Spanner?使用您的用户 ID 作为键,使用积分作为值。

标签: node.js express firebase-realtime-database google-cloud-functions rate-limiting


【解决方案1】:

您需要对所使用的任何底层数据存储使用原子操作。由于您还没有说那是什么,因此无法就如何进行提供具体建议。大多数数据库都提供了一种使用“事务”的方法,该方法仅在满足某些条件时才允许更新成功。您将希望使用这些事务之一来确定客户端是否应该能够继续更新。

确实没有简单的方法可以让 Cloud Functions 以一种可扩展的方式限制每个用户的函数调用率。这实际上是关于允许太多并发请求的底层存储机制。如果您不必增加用户数量,您可以使用Cloud Tasks 为每个用户实现一个队列,但我认为这并不是最好的解决方案。

【讨论】:

  • 我能以这种方式使用 firebase-realtime-database 事务吗?
  • 是的,实时数据库有事务。
  • 我正在使用实时数据库事务来减少用户请求的信用,但我不确定如何使用它来阻止请求。
  • 您不会使用它来阻止请求。如果以前使用相同的 id 处理过请求,您将使用它来使请求失败。您将需要使用您分配的 ID 维护一些状态,以指示给定的请求交易是否已被应用。
  • 当你提到交易时我想到的是,由于我已经使用交易来减少信用,当减少值大于交易回调中的当前信用值时,我可能会失败请求。因为我不一定需要因为该用户最近有另一个请求而使请求失败
猜你喜欢
  • 2019-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-20
相关资源
最近更新 更多