AppSync订阅机制:start_ack后仍可能丢失事件的技术剖析

本文深入探讨AWS AppSync实时订阅协议的一个潜在问题:即使客户端收到start_ack确认消息,后续事件仍可能丢失。文章分析了问题成因、对"先订阅后查询"模式的影响,并提供了故障排查思路。

AppSync订阅机制:等待start_ack仍可能导致事件丢失

在AppSync中,即使订阅启动后收到了start_ack确认响应,也并不能保证所有后续事件都能被成功送达。

订阅是AppSync用于传递实时事件的机制,它基于WebSocket协议,相关协议文档可在此处查阅。在该协议中,客户端需要发送一个包含GraphQL查询的start消息来开始接收更新。随后,如果一切正常,AppSync会响应一个start_ack,并在有更新发生时发送数据事件。

阅读文档时,我的理解是start_ack标志着订阅已激活,所有未来事件都将被送达。但我观察到的实际情况并非如此。即使事件严格在收到start_ack之后才被触发,有时它仍然无法送达客户端。

为什么这是个问题?

具有实时更新功能的API的一个常见模式是:先订阅更新,然后再查询当前状态。这样可以避免出现更新丢失的"时间死区"。但这要求有一个明确的时间点来确认订阅已生效。如果没有这个保证,那么订阅就只是"尽力而为",消息仍会不时丢失,特别是在事件发生前一刻才建立订阅的情况下——这在测试和某些异步工作流中很常见。

实时更新,尤其是在AppSync中,是一个复杂的话题,很容易出错。我之前写过相关文章,在我的书中也有专门章节讨论它,我甚至还开发了一个库,因为我对AWS提供的库不太满意。

我注意到使用订阅的测试用例超时的情况已经持续了很长时间,但我之前将其归咎于"某些复杂因素",并添加了一些重试机制来处理。一个消息发布到IoT Core,触发一个Lambda函数,该函数写入DynamoDB,然后触发订阅。中间环节很多,所以偶尔需要十来秒的情况也是合理的。

但后来我开始研究一个更简单的设置,仍然注意到有些事件似乎从未到达。这次我可以定位问题了,因为如果在此之前并行打开了另一个订阅,事件就能在那个订阅中送达。所以问题必定在于:即使AppSync声称订阅已激活,但实际上它并未生效。

希望这个问题能尽快得到修复。

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