跳到主要内容
英文版本为准

本页译自英文,由模型翻译。若与英文原文存在差异,以英文原文为准。

结算

ack、retry、retry_after 和 drop 在 SQS 上变成什么:每种结果都是针对队列的一次调用,重试在队列本身中等待。

处理器的每种结果、它发出的 SQS 调用,以及消息的去向结果SQS 调用效果ackDeleteMessage消失retry()ChangeMessageVisibility(0)立即可见retry_after(d)ChangeMessageVisibility(d)d 之后回来,不晚于接收后12 小时dropDeleteMessage;达到上限时:Visibility(0)消失,或移入死信队列未结算就被丢弃不发调用,延长停止超时到期后回来
以文字阅读本图
  1. 结果: ack; retry(); retry_after(d); drop; 未结算 就被丢弃
  2. SQS 调用: DeleteMessage; ChangeMessage Visibility(0); ChangeMessage Visibility(d); DeleteMessage; 达到上限时: Visibility(0); 不发调用, 延长停止
  3. 效果: 消失; 立即可见; d 之后回来, 不晚于接收后 12 小时; 消失, 或移入 死信队列; 超时到期 后回来
  4. ack → DeleteMessage
  5. DeleteMessage → 消失
  6. retry() → ChangeMessage Visibility(0)
  7. ChangeMessage Visibility(0) → 立即可见
  8. retry_after(d) → ChangeMessage Visibility(d)
  9. ChangeMessage Visibility(d) → d 之后回来, 不晚于接收后 12 小时
  10. drop → DeleteMessage; 达到上限时: Visibility(0)
  11. DeleteMessage; 达到上限时: Visibility(0) → 消失, 或移入 死信队列
  12. 未结算 就被丢弃 → 不发调用, 延长停止
  13. 不发调用, 延长停止 → 超时到期 后回来

retry_after(d) 以整秒计算延迟并向上取整,因此消息绝不会早于 d 回来。超出接收后 12 小时的延迟会缩短到这 12 小时结束为止,本 crate 同时记录一条注明队列名称的警告日志。未结算就被丢弃的投递不发出任何调用:它的延长停止,消息在当前超时到期时回来。

SQS 没有只拒绝而不删除消息的操作,所以 drop 会删除消息。注册声明了重新驱动策略的队列是例外。在这种队列上,已被接收 maxReceiveCount 次的投递会被交还而不是删除,因为正是下一次接收把它移入死信队列,删除则会让它丢失。

投递的 redelivery_count 就是队列的 ApproximateReceiveCount,第一次投递算作一次。它统计每一次接收,包括超时到期后的接收,而不仅是服务请求的重试。

重试​

SQS 上的重试:消息在队列中等待,由重新驱动策略在下一次接收时决定去向一次投递接收计数表明这是第几次尝试处理器返回retry_after(d) 或 retry()ChangeMessageVisibility(d)消息在队列中等待下一次接收:这条消息是否已被接收 maxReceiveCount 次?还没有:再次投递,仍是同一条消息是:SQS 把它移入死信队列在最后一次允许的接收上 drop,会以可见性 0 交还消息,于是 SQS 移走它,而不是丢失它队列保存着等待中的消息:服务崩溃不会丢失任何重试
以文字阅读本图
  1. 一次投递 接收计数表明这是第几次尝试 → 处理器返回 retry_after(d) 或 retry(): 已处理
  2. 处理器返回 retry_after(d) 或 retry() → ChangeMessageVisibility(d) 消息在队列中等待: 一次重试
  3. ChangeMessageVisibility(d) 消息在队列中等待 → 下一次接收:这条消息是否已被 接收 maxReceiveCount 次?: d 之后
  4. 下一次接收:这条消息是否已被 接收 maxReceiveCount 次? → 还没有: 再次投递, 仍是同一条消息: 还没有
  5. 下一次接收:这条消息是否已被 接收 maxReceiveCount 次? → 是:SQS 把它 移入死信队列: 是
  6. 在最后一次允许的接收上 drop,会以可见性 0 交还消息, 于是 SQS 移走它,而不是丢失它
  7. 队列保存着等待中的消息: 服务崩溃不会丢失任何重试

重试从不离开队列。retry_after(d) 让消息在 d 内不可见,然后它作为同一条消息回来,id 不变,接收计数加一。没有任何东西被重新发布,因此运行时的重新发布回退在这里从不运行,.out_retry(..) 在 SqsQueue 上无法编译。可见性的结束时间晚于接收后 12 小时时,SQS 会拒绝它。

max_attempts(n) 与 dead_letter(q) 合起来就是队列的重新驱动策略:maxReceiveCount 是 n,死信队列是 q。订阅打开时把这个策略写到队列上,由 SQS 统计接收次数,并自行移走用尽次数的消息。只设其中一项,启动时就会得到 SqsError::IncompleteRedrive。

队列保存着等待中的消息,所以服务崩溃不会丢失任何重试:消息在可见性结束时回来,交给下一个轮询的消费者。