Эта страница переведена с английского языковой моделью. При любом расхождении верен английский оригинал.
Урегулирование
Чем ack, drop, retry и retry_after становятся в AMQP 1.0: диспозицией, на которую действует
брокер, и копиями, которые рантайм публикует в тот же адрес.
Схема текстом
- Обработчик: ack(); retry(); retry_after(d); drop(); нет исхода до ухода связи
- Диспозиция: accepted; modified delivery-failed; rejected, копия через d; rejected; ничего
- Брокер: готово: сообщение уходит из очереди; обратно в очередь, счёт на одну больше; копия - новое сообщение в адресе; решает политика недоставленных сообщений брокера; обратно в очередь, когда связь отсоединится
- ack() → accepted
- accepted → готово: сообщение уходит из очереди
- retry() → modified delivery-failed
- modified delivery-failed → обратно в очередь, счёт на одну больше
- retry_after(d) → rejected, копия через d
- rejected, копия через d → копия - новое сообщение в адресе
- drop() → rejected
- rejected → решает политика недоставленных сообщений брокера
- нет исхода до ухода связи → ничего
- ничего → обратно в очередь, когда связь отсоединится
- При at-most-once доставки приходят урегулированными: ack, retry и drop возвращают AckError::Unsupported
По умолчанию подписка работает в режиме at-least-once. Доставка остаётся неурегулированной, пока исход обработчика не дойдёт до задачи приёма и не станет диспозицией. Доставка, которая так и не получила диспозицию, остаётся на связи, и брокер возвращает её в очередь, когда связь отсоединяется или соединение обрывается.
retry() отправляет modified с delivery-failed, а не released. released сообщает брокеру,
что доставку не обрабатывали, и оставляет delivery-count прежним. Обработчик, который просит
повтор, обработал доставку и вернул ошибку, а предел попыток читает именно этот счётчик. Без
увеличения счётчика сообщение, которое всегда возвращает ошибку, возвращалось бы бесконечно.
undeliverable-here остаётся false, поэтому сообщение может вернуться в ту же подписку.
Settle::AtMostOnce урегулирует каждую доставку при
получении.
| Исход | At most once |
|---|---|
ack, drop | AckError::Unsupported с записью в журнал: доставка урегулирована при получении |
retry() | AckError::Unsupported; при объявленном пределе - сразу копия, если у доставки нет delivery-count |
retry_after(d) | копия, опубликованная в адрес через d |
| нет исхода | ничего: брокер уже отпустил сообщение |
Сколько раз сообщение доставлялось, показывает delivery-count + 1, и именно это число возвращает
redelivery_count. У сообщения, которое опубликовал этот
крейт, нет секции header, поэтому у него нет и счётчика, и вместо него считает заголовок
фреймворка с номером повтора.
Повторы
Схема текстом
- Доставка: номер попытки - delivery-count + 1, у копии - x-ruststream-retry-count → Обработчик возвращает retry() или retry_after(delay): обработана
- Обработчик возвращает retry() или retry_after(delay) → max_attempts: попытка ниже предела?: повтор
- max_attempts: попытка ниже предела? → retry(): modified, обратно в очередь: ниже
- max_attempts: попытка ниже предела? → retry_after: rejected, копия через задержку
- max_attempts: попытка ниже предела? → На пределе: копия в адрес недостав- ленных: на пределе
- max_attempts: попытка ниже предела? → На пределе, без адреса недостав- ленных: rejected
- retry(): modified, обратно в очередь → Оба пути возвращаются в адрес подписки
- retry_after: rejected, копия через задержку → Оба пути возвращаются в адрес подписки
- Копия ждёт своей задержки внутри процесса: остановка до срабатывания таймера её теряет
Предел задаётся в точке монтирования через
max_attempts, и первая доставка считается
первой попыткой. Ниже предела retry() возвращает сообщение брокеру с modified, и брокер его
учитывает. У копии нет счётчика брокера, поэтому при объявленном пределе retry() копии сразу
публикует следующую копию.
AMQP 1.0 не придерживает сообщения, поэтому retry_after выполняет
сам рантайм. Он отклоняет
доставку, ждёт задержку и публикует копию, увеличив заголовок с номером повтора на единицу. Копия
уходит в собственный адрес подписки, потому что получатель присоединяет свой источник, а
отправитель свою цель к одному и тому же узлу. В адресе queue копия конкурирует за получателей,
как любое другое сообщение, а в адресе topic её получает каждая подписка.
На пределе доставка публикуется в том виде, в каком пришла, в адрес недоставленных сообщений. Если такой адрес не объявлен, доставка отклоняется, и дальше решает собственная политика недоставленных сообщений брокера. Адрес недоставленных сообщений, объявленный без предела, принимает каждый повтор.