如何在无服务器lambda应用程序上实现速率限制



目前我有一个使用lambda和API网关的无服务器API。

我想要构建的下一个功能是使用AWS cognito进行用户身份验证,然后对每个用户应用速率限制。

我该怎么做?API网关能与cogito通信吗?

我阅读了AWS文档:

Per-client节流限制适用于使用与您的使用策略关联的API密钥作为客户端标识符的客户端。

然而,据我所知,这是指用于调用lambda的每个x-api-key的速率限制。

我真的不想为每个用户创建一个新的密钥,因为一次发布10000个密钥的硬性限制。我更愿意使用cognito用户池密钥。

我知道另一种方法是,建立一个自定义授权器,将用户ID写入内存数据库,如Redis或ElastiCache,然后在每次请求时都会查询该数据库,以计算用户最后一次发出请求的时间。

然而,我并不喜欢这种方法,因为它的可扩展性不如无服务器的API,可能会成为整个API的瓶颈。

每个人是如何实施这样的利率限制的?我错过了一些基本的东西吗?亚马逊有现成的解决方案吗?

AWS API网关更适合于点对点连接的客户端凭据oAuth身份验证流。它没有提供太多功能,例如基于用户的速率限制。您可以将lambda授权器与dynamodb一起使用,以存储用户限制和当前值,并根据用户提供速率限制。AWS API网关没有提供基于用户的限制功能。

编写自定义授权程序将是最常见的最佳实践之一。这也不是瓶颈,因为这个自定义授权程序本身就是一个动态扩展的Lambda。

迭代开发您的自定义授权程序:

1.Lambda+Cognito

如果您真的更喜欢Cognito,请将您的Lambda连接到Cognito并从Lambda事件中请求用户信息。检查用户是否存在于Cognito中,并可能检查用户是否是特定组的成员。这可以使用SDK来完成,例如用于Python的boto3。要将API请求减少到Cognito,请使用API网关中的缓存。将其设置为例如300秒。因此,只有每五分钟才会请求Cognito API。

2.优化性能

如果迭代1让我们得出结论,这个过程会减慢速度,那么使用最小的redis实例并存储redis所需的信息。将过期时间设置为30分钟。如果redis中有可用的条目,请将自定义授权程序的行为更改为先检查。如果是,则在值未过期的情况下使用此信息。如果不是,则调用Cognito API并将结果也存储在redi中。现在,您的系统将只调用redis的所有5分钟(因为API网关中的缓存)和Cognito API的所有30分钟,因为redis 中对象的过期时间

3.优化稳定性

如果一切正常,你就可以在稳定中工作。例如,检查redis是否可用(reds-ping)。。。如果没有,不要抛出错误,就像没有redis一样继续操作。如果无法访问Cognito,请扩展已过期的对象,以确保用户能够在解决Cognito问题时登录。

4.可选:丰富您的数据

您可以丰富数据,比如通过添加DynamoDB并请求这些数据来进行进一步的检查。将这些信息也存储在redis中,将缩短自定义授权程序Lambda本身的执行时间。

总结

总而言之,使用API网关中的Cache,Redis可以减少对用户后端(如Cognito)的请求,并减少依赖关系中的单点故障(如使用reds-ping进行检查),如果用户能够登录/调用API,则您可以拥有一个自定义授权器,该授权器将在不到100ms的时间内进行检查。

开箱即用,您只有API密钥用于;"无用户";批准10.000的限制是可以增加的,但你也必须实现一个服务来将密钥附加到用户。。。这可以通过使用Cognito用户池中的触发器来实现(如果要创建用户,请创建新的API密钥并使用SES将其发送给用户)。。。但是你必须为删除用户等用例编写更多的触发器/函数

我们目前正试图解决这个完全相同的问题,因为我们即将达到10000个密钥的硬限制。我不知道为什么这不是无限的支持开发者SaaS类型的业务,在那里你可能有数百万用户。无论如何

我们正在使用自定义授权程序来验证用户,并已尝试使用此库https://github.com/blackflux/lambda-rate-limiter.它似乎工作正常,并使用内存存储来跟踪请求。这确实意味着Lambda必须保持温暖,理论上可以在多个Lambda中跟踪用户,但它可能足够可靠。

还看了一下这个:https://github.com/animir/node-rate-limiter-flexible,它有一堆存储适配器,但不幸的是没有我们更喜欢的DynamoDB。如果我们超过了Lambda解决方案,这可能是下一步,我们创建自己的DDB适配器或使用Redis。

使用自己的速率限制的缺点是,据我所知,你必须关闭自定义authorizer缓存,这是一个很好的功能,意味着你的authorizer不会在每个请求上运行(你基本上必须在每个请求中运行2个Lambdas)。因此,我们正在权衡这与利率限制的利弊。

我们也从安全角度考虑WAF,但这不会对单个用户进行评级限制。

我不能提供一个明确的答案,但这些是我们目前正在考虑的选项。

最新更新