在从CLI或从AWS控制台创建http端点的新SNS订阅后,我收到亚马逊的请求以确认订阅。我的代码执行确认,然后我从亚马逊获得使用SubscriptionArn成功确认订阅的响应。同样在AWS Console中,我看到订阅已确认。
但几秒钟后我收到亚马逊的另一个确认请求。脚本尝试处理它,但亚马逊发送错误消息"Subscription already confirmed"
。这种情况重复了几次。
为什么亚马逊即使在确认后也会发送确认请求?是否可以检查订阅是否已经确认且未执行confirmSubscription
?
P.S。:我使用NodeJS SDK确认订阅。
由于
答案 0 :(得分:2)
如果Amazon SNS未从您的终端收到成功的响应,它会尝试再次发送该消息。这适用于所有消息,包括订阅确认消息。
从概念上讲,发生的事情似乎必须是这样的:SNS的一部分(需要确认订阅的部分)基本上要求SNS的不同部分(传递HTTP消息的部分)到HTTP端点)以向您的端点传递消息。在这种情况下,它是确认消息。
与任何其他消息一样,原始发件人不会被询问是否应重试失败的消息 - SNS只是重试它。即使原始发件人恰好是SNS的不同内部部分,如同订阅确认一样,这似乎仍然适用。
没有响应HTTP响应代码,告诉SNS你收到消息会导致SNS在几秒钟后再次尝试...所以即使你已经确认了你的订阅,SNS的一部分已经完成了任务向你传达的信息是不知道的 - 从它的角度来看,它只知道你显然没有收到的消息,这意味着重试。
每次重试时,正在重试的消息将具有相同的x-amz-sns-message-id:
请求标头。这使您能够区分重试的消息和看起来与先前消息相同的消息,但实际上是具有相同有效负载的不同消息。
在上面链接的同一页面中,在指定时间内200到499之间的任何响应代码都被视为成功交付。
确保您的终端使用适当的状态代码响应来自Amazon SNS的HTTP
POST
消息。连接将在15秒后超时。如果您的端点在连接超时之前没有响应,或者您的端点返回200-4xx范围之外的状态代码,则Amazon SNS会将该消息的传递视为失败尝试。
将4xx状态代码包含在"成功"的概念中。在考虑到什么"交付"的概念之前,这似乎是违反直觉的。意味着 - 这意味着您的端点接收消息。 4xx响应表明您的端点没有以某种方式喜欢消息,但确实传递了消息。这与5xx错误形成对比,在一般意义上,这意味着您的端点不会 - 至少在此时 - 能够处理消息。
这种行为也表明了另一个设计考虑因素:作为对#34;丢失"如果您的应用程序尝试联系SNS端点以完成确认失败,则您的应用程序应返回5xx错误以返回SNS,以便SNS再次尝试并且该过程可能随后成功。