Перейти к основному содержимому
Нормативная версия документации - английская

Эта страница переведена с английского языковой моделью. При любом расхождении верен английский оригинал.

Урегулирование

Чем ack, drop, retry и retry_after становятся в AMQP 1.0: диспозицией, на которую действует брокер, и копиями, которые рантайм публикует в тот же адрес.

Каждый исход обработчика на подписке at-least-once: диспозиция, которую отправляет подписка, и то, что делает брокерОбработчикДиспозицияБрокерack()acceptedготово:сообщениеуходит из очередиretry()modifieddelivery-failedобратнов очередь, счётна одну большеretry_after(d)rejected,копия через dкопия - новоесообщениев адресеdrop()rejectedрешает политиканедоставленныхсообщений брокеранет исходадо уходасвязиничегообратнов очередь, когдасвязь отсоединитсяПри at-most-once доставки приходят урегулированными: ack, retryи drop возвращают AckError::Unsupported
Схема текстом
  1. Обработчик: ack(); retry(); retry_after(d); drop(); нет исхода до ухода связи
  2. Диспозиция: accepted; modified delivery-failed; rejected, копия через d; rejected; ничего
  3. Брокер: готово: сообщение уходит из очереди; обратно в очередь, счёт на одну больше; копия - новое сообщение в адресе; решает политика недоставленных сообщений брокера; обратно в очередь, когда связь отсоединится
  4. ack() → accepted
  5. accepted → готово: сообщение уходит из очереди
  6. retry() → modified delivery-failed
  7. modified delivery-failed → обратно в очередь, счёт на одну больше
  8. retry_after(d) → rejected, копия через d
  9. rejected, копия через d → копия - новое сообщение в адресе
  10. drop() → rejected
  11. rejected → решает политика недоставленных сообщений брокера
  12. нет исхода до ухода связи → ничего
  13. ничего → обратно в очередь, когда связь отсоединится
  14. При 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, dropAckError::Unsupported с записью в журнал: доставка урегулирована при получении
retry()AckError::Unsupported; при объявленном пределе - сразу копия, если у доставки нет delivery-count
retry_after(d)копия, опубликованная в адрес через d
нет исходаничего: брокер уже отпустил сообщение

Сколько раз сообщение доставлялось, показывает delivery-count + 1, и именно это число возвращает redelivery_count. У сообщения, которое опубликовал этот крейт, нет секции header, поэтому у него нет и счётчика, и вместо него считает заголовок фреймворка с номером повтора.

Повторы​

Повтор в AMQP 1.0: предел попыток выбирает между возвратом сообщения, адресом недоставленных сообщений и отказомДоставка: номер попытки - delivery-count + 1,у копии - x-ruststream-retry-countОбработчик возвращаетretry() или retry_after(delay)max_attempts: попытка ниже предела?retry():modified,обратнов очередьretry_after:rejected,копия череззадержкуНа пределе:копияв адреснедостав-ленныхНа пределе,без адресанедостав-ленных:rejectedОба пути возвращаютсяв адрес подпискиКопия ждёт своей задержки внутри процесса:остановка до срабатывания таймера её теряет
Схема текстом
  1. Доставка: номер попытки - delivery-count + 1, у копии - x-ruststream-retry-count → Обработчик возвращает retry() или retry_after(delay): обработана
  2. Обработчик возвращает retry() или retry_after(delay) → max_attempts: попытка ниже предела?: повтор
  3. max_attempts: попытка ниже предела? → retry(): modified, обратно в очередь: ниже
  4. max_attempts: попытка ниже предела? → retry_after: rejected, копия через задержку
  5. max_attempts: попытка ниже предела? → На пределе: копия в адрес недостав- ленных: на пределе
  6. max_attempts: попытка ниже предела? → На пределе, без адреса недостав- ленных: rejected
  7. retry(): modified, обратно в очередь → Оба пути возвращаются в адрес подписки
  8. retry_after: rejected, копия через задержку → Оба пути возвращаются в адрес подписки
  9. Копия ждёт своей задержки внутри процесса: остановка до срабатывания таймера её теряет

Предел задаётся в точке монтирования через max_attempts, и первая доставка считается первой попыткой. Ниже предела retry() возвращает сообщение брокеру с modified, и брокер его учитывает. У копии нет счётчика брокера, поэтому при объявленном пределе retry() копии сразу публикует следующую копию.

AMQP 1.0 не придерживает сообщения, поэтому retry_after выполняет сам рантайм. Он отклоняет доставку, ждёт задержку и публикует копию, увеличив заголовок с номером повтора на единицу. Копия уходит в собственный адрес подписки, потому что получатель присоединяет свой источник, а отправитель свою цель к одному и тому же узлу. В адресе queue копия конкурирует за получателей, как любое другое сообщение, а в адресе topic её получает каждая подписка.

На пределе доставка публикуется в том виде, в каком пришла, в адрес недоставленных сообщений. Если такой адрес не объявлен, доставка отклоняется, и дальше решает собственная политика недоставленных сообщений брокера. Адрес недоставленных сообщений, объявленный без предела, принимает каждый повтор.