MS Graph API Webhook订阅与AWS API Gateway的神秘超时问题

本文详细探讨了在使用Microsoft Graph API Webhook订阅与AWS API Gateway集成时遇到的随机超时问题。作者分享了实现架构、验证流程、问题现象分析,并提出了通过切换到公共ALB的解决方案,为类似技术场景提供了实用参考。

MS Graph API Webhook订阅与AWS API Gateway的神秘超时问题

Microsoft Graph API支持一种订阅资源类型,用于管理其Webhook实现,以向客户端传递变更通知。订阅功能适用于多种资源,包括Outlook消息——这完美契合了我管理O365中共享收件箱传入消息的需求。

高层次上,实现流程如下:

  • 发起订阅请求,提供自定义的notificationUrl端点
  • 响应通知验证请求
  • 开始在处理程序上处理Webhook
  • 定期更新上述订阅——最大过期时间取决于资源类型

实现方案

我的方法相当直接:将API Gateway连接到用于处理Webhook的Lambda函数,并使用CloudWatch规则触发订阅生命周期管理的Lambda。

重要的是,API Gateway背后的Lambda(Webhook请求/响应处理程序)除了处理实际的订阅通知外,还处理初始订阅验证。以下是验证过程要求的简要总结:

  • 接受传入的HTTP POST请求,查询字符串中包含validationToken
  • 解码并转义令牌值
  • 返回HTTP响应,包含:
    • 正文包含解码后的令牌
    • 状态码为200
    • 内容类型为text/plain
    • 在10秒内交付

Outlook消息的最大过期时间为4230分钟(不到三天),因此我设置了CloudWatch规则每天运行一次以确保安全。这工作得非常完美——每天,订阅扩展Lambda都会被调用,Graph API会成功回复。整个往返时间,包括对Webhook监听器的验证请求,通常在一秒内完成。

神秘超时

上述实现按预期工作了数月——直到某一天,我开始在更新/扩展订阅时收到错误:

1
2
3
4
{
  "code": "InvalidRequest",
  "message": "Subscription validation request timed out."
}

在我们端没有代码或基础设施变更的情况下,我开始通过手动运行订阅更新请求来调试,例如:

1
2
3
4
5
6
PATCH https://graph.microsoft.com/v1.0/subscriptions/{id}
Content-type: application/json

{
   "expirationDateTime":"2020-09-22T18:23:45.9356913Z"
}

前几次尝试都失败了,错误与上述相同——然而,在第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片段。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计