Эта страница переведена с английского языковой моделью. При любом расхождении верен английский оригинал.
Завершение
Чем ack, drop, retry и retry_after становятся в
MQTT: одним подтверждением при QoS 1 и 2, ничем при QoS 0 и копиями, которые публикует рантайм.
Схема текстом
- Обработчик: ack(); drop(); retry(); retry() при пределе; retry_after(d); нет исхода: пакет отпущен
- Отправлено: PUBACK PUBREC; PUBACK PUBREC; ничего; PUBACK PUBREC; PUBACK PUBREC; ничего; При QoS 0 ничего не отправляется, ack и drop возвращают AckError::Unsupported, а копия рантайма уходит
- Затем: готово; готово, сообщение отпущено; вернётся при возобновлении сессии; копия публикуется сразу; копия публикуется через d; как retry(): вернётся при возобновлении
- ack() → PUBACK PUBREC
- PUBACK PUBREC → готово
- drop() → PUBACK PUBREC
- PUBACK PUBREC → готово, сообщение отпущено
- retry() → ничего
- ничего → вернётся при возобновлении сессии
- retry() при пределе → PUBACK PUBREC
- PUBACK PUBREC → копия публикуется сразу
- retry_after(d) → PUBACK PUBREC
- PUBACK PUBREC → копия публикуется через d
- нет исхода: пакет отпущен → ничего
- ничего → как retry(): вернётся при возобновлении
У MQTT есть один ответ на доставку - подтверждение: PUBACK при QoS 1, PUBREC при QoS 2. ack
отправляет его. drop тоже отправляет его, потому что подтверждение - единственный способ, которым
протокол позволяет сервису закончить с сообщением.
В MQTT нет отрицательного подтверждения, поэтому на живом соединении сервер никогда не отправляет
сообщение повторно. retry() без объявлений возвращает
AckError::Unsupported, рантайм записывает это в журнал, а доставка остаётся неподтверждённой.
Сервер отправляет её повторно, только когда постоянная сессия возобновляется на новом соединении.
До тех пор она занимает один слот в окне Receive Maximum: когда окно заполнено
такими доставками, сервер не отправляет по соединению новых сообщений с QoS 1 и QoS 2. Пакет,
который обработчик отпустил, так же остаётся неподтверждённым.
Переобработка в пределах сессии - это копия, которую публикует рантайм. retry_after(d)
подтверждает оригинал, ждёт d и публикует копию. retry() при объявленном пределе или теме для
недоставленных сообщений публикует копию сразу. У доставки с QoS 0 подтверждать нечего, а её
копия всё равно уходит.
| Исход | QoS 0 |
|---|---|
ack, drop | AckError::Unsupported |
retry() | AckError::Unsupported; при объявленном пределе копия публикуется сразу |
retry_after(d) | копия публикуется через d |
| нет исхода | ничего |
Переобработка
Схема текстом
- Ниже предела: Оригинал подтверждён, копия ждёт d; MqttTopic: копия уходит в его тему; MqttFilter: в тему, которую называет точка монтирования
- На пределе: Тема для недоставленных: доставка публикуется туда; Без темы для недоставленных: подтверждена и отпущена
- Доставка номер попытки читается из x-ruststream-retry-count → Обработчик возвращает retry_after(d) или retry() при объявлении: обработана
- Обработчик возвращает retry_after(d) или retry() при объявлении → max_attempts: эта попытка ниже предела?: переобработка
- max_attempts: эта попытка ниже предела? → Ниже предела: ниже
- max_attempts: эта попытка ниже предела? → На пределе: на пределе
- Копия - обычная публикация: её получает каждая подписка, фильтр которой подходит к её теме. Копию, ждущую задержки, держит процесс, и падение до срабатывания таймера её теряет.
Предел объявляется в точке монтирования через
max_attempts, и первая доставка считается
первой попыткой. MQTT сам не считает доставки, поэтому рантайм считает опубликованные копии в
заголовке каждой копии x-ruststream-retry-count.
Ниже предела копия уходит по адресу, который даёт форма подписки.
MqttTopic, в том числе совместный, указывает на
собственную тему, поэтому его регистрация ничего не называет.
MqttFilter подходит ко многим темам и не публикует
ни в одну из них, поэтому его регистрация называет тему
для копии: один раз или для каждой доставки через преобразование. Если регистрация фильтра не
называет тему ни одним из этих способов, приложение не запускается.
На пределе доставка уходит в тему для недоставленных сообщений с неизменной полезной нагрузкой. Если тема для недоставленных сообщений не объявлена, доставка подтверждается и отпускается.
Копия - обычная публикация, поэтому её получает каждая подписка, фильтр которой подходит к её теме, в этом сервисе и в других. Тема для недоставленных сообщений, к которой подходит живой фильтр, сразу возвращает сообщение обратно, поэтому ей нужно имя, которое не читает ни одна подписка. Копию, которая ждёт задержки, держит процесс: штатная остановка её дожидается, а падение до срабатывания таймера её теряет.