Что происходит между продюсером и консьюмером в RabbitMQ
Что проверяют
Знаете ли вы устройство доставки: обменник, привязка, очередь, подтверждение. Для .NET к этому добавляется вторая половина вопроса: как обращаться с клиентом, потому что почти все ошибки там про многопоточность и время жизни объектов.
Как отвечать
Сначала коротко про путь: продюсер публикует в обменник с ключом маршрутизации, обменник по типу и привязкам раскладывает копии по очередям, очередь хранит сообщение, консьюмер забирает и подтверждает. Смысл в том, что напрямую стороны друг о друге не знают и могут жить порознь.
Дальше про .NET:
- соединение тяжёлое и живёт долго, его регистрируют одиночкой. Каналы дешёвые, но делить один канал между потоками нельзя, на каждый обработчик свой;
- размер выдачи задаётся на канал. Без него один консьюмер заберёт всю очередь, и второй экземпляр сервиса будет простаивать;
- потребление строится на событии получения сообщения. В новых версиях клиента интерфейс канала стал асинхронным, и подписку надо ожидать, а не вызывать из
async void; - подтверждение отправляется по тегу доставки, отказ с возвратом или без, во втором случае сообщение уходит в обменник мёртвых сообщений;
- надёжность публикации это подтверждения брокера плюс флаг обязательной маршрутизации с обработчиком возврата;
- поверх клиента часто берут готовую шину: она закрывает сериализацию, повторы и версии сообщений.
Где спотыкаются
Открывают соединение на каждый запрос, потому что зарегистрировали его во внедрении зависимостей с коротким временем жизни. Под нагрузкой брокер упирается в число соединений, а в логе приложения видно только таймауты.
Второе: делят один канал между потоками. Протокол этого не допускает, получаются ошибки кадра и внезапно закрытые каналы, которые не воспроизводятся при отладке одного запроса.
Третье: подтверждают сообщение сразу при получении, до сохранения результата. Исключение в обработчике означает, что сообщение уже удалено из очереди. Подтверждение ставится после успешной работы, а исключение переводится в отказ с осознанным решением про возврат.