英文版本为准
本页译自英文,由模型翻译。若与英文原文存在差异,以英文原文为准。
结算
ack、drop、retry 和 retry_after 在 Pulsar 上变成什么:确认,以及 Broker 计入客户端死信策略的重新投递。
以文字阅读本图
- 处理器: ack(); retry(); retry_after(d); drop(); 没有结果
- 本 crate 调用: ack_with_id; nack_with_id; 等待 d,然后 nack_with_id; ack_with_id; 什么也不做; 客户端的计时器 稍后处理; 只有 Shared 和 KeyShared 订阅的计数会增加: 其他类型不计数
- Broker: 已确认, 不再发送; 立即 再次发送, 计数 + 1; d 之后 再次发送, 计数 + 1; 已确认: 消失; ack_timeout 之后 再次发送, 计数 + 1
- ack() → ack_with_id
- ack_with_id → 已确认, 不再发送
- retry() → nack_with_id
- nack_with_id → 立即 再次发送, 计数 + 1
- retry_after(d) → 等待 d,然后 nack_with_id
- 等待 d,然后 nack_with_id → d 之后 再次发送, 计数 + 1
- drop() → ack_with_id
- ack_with_id → 已确认: 消失
- 没有结果 → 什么也不做; 客户端的计时器 稍后处理
- 什么也不做; 客户端的计时器 稍后处理 → ack_timeout 之后 再次发送, 计数 + 1
每种结果都是对订阅的客户端消费者的一次调用,由订阅的驱动任务发出。ack 和 drop 都确认消息,因为 Pulsar 没有永久拒绝消息的命令:不应再回来的消息被确认,一再失败的消息则因上限进入死信主题。retry 请求 Broker 立即再次投递它。
retry_after(d) 在服务中把投递保持在未确认状态 d 这么久,然后发出同样的否定确认。等待运行在 Broker 建立连接的那个运行时上。不短于订阅 ack_timeout 的延迟会被拒绝,因为客户端的计时器会先把消息送回来。
没有处理器结算的投递保持未确认状态。设置了 ack_timeout 时,超时一过,客户端就会再次请求它,确认一页用图说明了这一点。没有设置时,只有消费者断开连接后它才会回来。
重试
以文字阅读本图
- 一次投递 Broker 统计它的重新投递次数 → 处理器返回 retry() 或 retry_after(d): 已处理
- 处理器返回 retry() 或 retry_after(d) → retry(): 立即发出 否定确认
- 处理器返回 retry() 或 retry_after(d) → retry_after(d):在进程中 扣留 d, 然后同上
- retry(): 立即发出 否定确认 → Broker 再次投递它 计数 + 1
- retry_after(d):在进程中 扣留 d, 然后同上 → Broker 再次投递它 计数 + 1
- Broker 再次投递它 计数 + 1 → 客户端的死信策略: 计数是否已达到 max_attempts?
- 客户端的死信策略: 计数是否已达到 max_attempts? → 低于上限: 处理器 再次收到它: 低于上限
- 客户端的死信策略: 计数是否已达到 max_attempts? → 到达上限:生产到 死信主题, 原消息已确认: 到达上限
- Exclusive 或 Failover 订阅上的上限 拒绝启动:这两种类型都不统计重新投递
- 等待期间停止,丢失的是等待而不是消息: 消息仍未确认
送回消息不需要发布任何东西:Broker 再次投递同一条消息,并为它计数。注册的 max_attempts 和死信主题变成客户端的死信策略。消息的计数低于上限时,客户端交出它,因此处理器会看到它 max_attempts 次。到达上限时,客户端把它生产到死信主题,并确认原消息。
这两项设置要一起使用:只声明其中一项的注册会拒绝启动;Exclusive 或 Failover 订阅上的上限也会拒绝启动,因为这两种订阅的消息到达时计数总是零。
计数归客户端自己所有,投递不会报告它。在 retry_after 等待期间停止的进程,丢失的是等待而不是消息:消息仍未确认,Broker 会在确认超时之后,或在消费者的连接断开后再次投递它。