解密MS Graph API Webhook订阅与AWS API Gateway的神秘超时问题
Microsoft Graph API支持一种订阅资源类型,用于管理其Webhook实现,以便向客户端传递变更通知。订阅功能适用于多种资源,包括Outlook消息——这完美契合了我管理O365共享收件箱中传入消息的需求。
高层次上,实现方案如下:
- 发起订阅请求,提供自定义的notificationUrl端点
- 响应通知验证请求
- 开始在监听器上处理Webhook
- 定期更新上述订阅——最大过期时间取决于资源类型
实现方案
我的方法相当直接:一个连接到Lambda处理器的API Gateway用于处理Webhook,以及一个CloudWatch规则来触发订阅生命周期管理Lambda。
重要的是,API Gateway背后的Lambda(Webhook请求/响应处理器)除了处理实际的传入订阅通知外,还处理初始订阅验证。以下是验证过程要求的快速总结:
- 接受传入的HTTP POST请求,查询字符串中包含validationToken值
- 解码并转义token值
- 返回HTTP响应,包含:
- 正文包含解码后的token
- 状态码为200
- 内容类型为text/plain
- 在10秒内交付
Outlook消息的最大过期时间为4230分钟(不到三天),因此我设置了CloudWatch规则每天运行一次以确保安全。这工作得非常完美——每天,订阅扩展Lambda都会被调用,Graph API会成功回复。总往返时间(包括对Webhook监听器的验证请求)通常在一秒内。
神秘超时
上述实现方案按预期工作了数月——直到有一天,在更新/扩展订阅时我开始收到错误:
|
|
在我们端没有代码或基础设施变更的情况下,我开始通过手动运行订阅更新请求来调试,例如:
|
|
前几次尝试都失败了,出现与上述相同的错误——然而,在第4或第5次尝试时成功了。在几轮测试中,这种情况随机发生,最终以成功响应结束。
正如问题开始前几个月所经历的那样,成功的请求几乎在一秒内返回。值得注意的是,失败的请求确实在某种程度上似乎超时了,因为我直到至少10秒过去后才收到HTTP 400。检查日志后,这些失败的请求似乎从未到达我们的基础设施。
假设
随机成功请求的性质,夹杂在从未到达我们端点的失败中,似乎暗示了某种类型的速率限制——要么在Microsoft端,要么可能在AWS的API Gateway上强制执行。可能是随着时间的推移,使用API Gateway开发的集成数量增加,达到了某个阈值,触发了对从MS Graph API到API Gateway连接的限流。使用公共Webhook监听器测试工具进行的额外故障排除无法重现此问题,似乎进一步指向了API Gateway特有的问题。
Graph API支持拒绝提供帮助,建议我们没有适当的企业支持计划。个人认为,此问题的性质不应需要企业支持计划。如果MS支持的任何人读到本文,我邀请您查看一下,因为这可能影响us-east-1中的其他实现。
解决方案
最终,我通过从API Gateway切换到公共ALB来解决此问题。供参考,这里有一个用于无服务器框架的便捷CloudFormation片段。