在 CloudFront 访问时触发 RDS lambda

Trigger RDS lambda on CloudFront access

我从 S3 BucketCloudFront 提供静态 JS 文件,我想监控访问它们的人,我不希望它通过 CloudWatch 等完成,我想自己登录

对于 CloudFront 的每个请求,我都想触发一个 lambda 函数,该函数将有关请求的数据插入到我的 MySQL RDS 实例中。

但是,CloudFront 限制了 Viewer Request Viewer Response 触发器过多,例如 1 秒超时(连接到 MySQL 时太短),lambda 没有 VPC 配置(因此我什至无法访问 RDS 子网)等等。

实现该目标的最佳方法是什么?设置 API Gateway 以及如何向那里发送请求?

处理从 CloudFront 访问的静态内容(或任何内容)的典型方法是启用日志记录,然后处理日志文件。

要启用 CloudFront Edge 事件(包括处理和更改事件),请查看 Lambda@Edge。

Lambda@Edge

我会先启用日志记录并监视流量一段时间。当坏人攻击您的网站(CloudFront Distribution)时,他们将产生大量流量。这可能会导致使用 Lambda Edge 产生一些可观的账单。我还建议查看 Amazon WAF 以帮助缓解拒绝服务攻击,这可能有助于处理 Lambda 的数量。

这似乎是一个次优策略,因为 CloudFront 在触发代码 运行ning 时暂停 request/response 处理——Lambda@Edge 触发器中的 Lambda 代码必须在处理之前完成执行请求或响应继续,因此超时很短。

CloudFront 提供每小时多次丢弃的日志(取决于流量负载)到您 select 的存储桶中,您可以从 S3 事件通知中捕获、解析并插入到您的数据库中。

然而...

如果您真的需要实时捕获,最好的办法可能是在您的 VPC 内创建第二个 Lambda 函数,它接受提供给 Lambda@ 的数据结构边沿触发。

然后,在查看器请求或查看器响应触发器的代码中,您需要做的就是使用内置的 AWS SDK 来调用您的第二个 Lambda 函数异步,将事件传递给它。

这样,日志记录任务就会被移交,您无需等待响应,CloudFront 处理可以继续。

我建议,如果你真的想走这条路,这将是最好的选择。一个 Lambda 函数可以轻松调用第二个函数,即使第二个函数不在同一账户、区域或 VPC 中,因为调用是通过与 Lambda 服务的端点通信完成的 API.

但是,还有一些优化的空间,因为你必须考虑到Lambda@Edge的另一个方面,它与此间接相关:

no VPC configuration to the lambda

这是有一个重要原因的。您的 Lambda@Edge 触发器代码位于最靠近处理每个特定查看器流量的边缘位置的区域中的 运行。您的 Lambda@Edge 函数在 us-east-1 中配置,但随后会复制到所有区域,准备好 运行 如果 CloudFront 需要它。

因此,当您调用上面提到的第二个 Lambda 函数时,您实际上会接触到第二个函数区域中的 Lambda API -- from 正在处理此特定请求的 Lambda@Edge 触发器的区域。

这意味着两个区域之间的距离越远,延迟就越多。

您真正的最佳解决方案(出于性能目的)稍微复杂一些:通过向Lambda API...您可以在每个区域创建一个 SNS 主题,并为每个区域订阅第二个 Lambda 函数。 (SNS 可以跨区域边界调用 Lambda 函数。)然后,您的 Lambda@Edge 触发器代码只需向其所在区域中的 SNS 主题发布一条消息,该消息将立即 return 响应并异步调用远程 Lambda 函数(第二个功能,在一个特定区域的 VPC 中)。在您的 Lambda@Edge 代码中,环境变量 process.env.AWS_REGION 为您提供了您当前 运行ning 所在的区域,因此您可以使用它来确定如何将消息发送到正确的 SNS 主题,以最少的成本潜伏。 (测试时,这始终是 us-east-1)。

是的,这有点令人费解,但它似乎是在不对请求处理施加大量延迟的情况下完成您尝试做的事情的方法 -- Lambda@Edge 尽快将信息传递给另一个服务将承担在数据库中实际生成日志消息的责任。

Lambda 和关系数据库对并发性、连接和连接池提出了严峻的挑战。有关详细信息,请参阅此 Lambda databases guide

我建议使用 Lambda@Edge 与为更高并发性构建的服务对话,作为记录访问的第一步。例如,您可以让 Lambda@Edge 函数将访问记录写入 SQS,然后让后台工作人员从 SQS 读取到 RDS。

这是一个 example of Lambda@Edge interacting with STS to read some config。它可以很容易地重构为写入 SQS。