Дмитрий, как я писал выше, канал открывается внутри TCP подключения, поэтому переподключение должно решить эту проблему. Но лучше что-то исправить, потому-что каждый канал занимает ресурсы со стороны RabbitMQ и если висит куча неиспользуемых каналов, то потребляется большое памяти и процессора.
Если есть механизм повторной отправки задачи в очередь, то есть и шанс повторной отправки пользователю, проверяйте актуальное состояние записи в БД перед отправкой.
Если нет требования к мгновенной отправке и нагрузка не такая большая, то может так же нет смысла добавления RabbitMQ в систему. Процесс, который слушает RMQ может по таймеру выгрибать из БД и сразу отправлять.
Слишком много не нужно, лучше использовать менеджер с пулом каналов.
Дополню немного. Да, хорошо держать пул, само открытие/закрытие канала тоже требует взаимодействие по сети. Но с точки зрения RabbitMQ канал это недорогой ресурс (Erlang процесс), поэтому если есть не так много клиентов, то даже 1000 каналов на каждом не должно скушать много ресурсов на сервере. Также канал позволит масштабироваться по всем ядрам процессора отпрвителю (процесс маршрутизации сообщений как раз происходит в рамках канала).
AMQP протокол нацелен больше на целостность данных, чем на возможность закинуть как можно больше сообщений одному отправителю. Если нужны гарантии - нужно подождать. Но как я написал выше, никто не мешает даже одному отправителю открыть несколько каналов по верх одного tcp подключения (по сути похоже на http/2).
К сожалению, книг я не знаю, да и статей, которые бы показывали почему нельзя так делать с цифрами.
Тут всё индивидуально, например, если у вас сервер с RabbitMQ имеет 100ГБ/с сеть, супер быстрые диски с достаточным объёмом, много оперативной памяти для кэша, а в свою очередь Вам надо отправить 100 видео в минуту по 50МБ каждое, то RabbitMQ и остальные пользователи такое даже не заметят.
Самое действенное и правильное - поднимите систему, которая ожидается в продакшете (или близкую к ней), и отправьте нагрузку которую ожидаете. Помониторьте день когда всё идет по плану, потом отрубите потребителей, подайте 2х/10х нагрузку и оцените, если такое поведение подходит.
Одной из проблем больших сообщений помню было то, что RMQ хранит сообщения в журналах (не деля на очереди), разбивая на куски по, например, 10ГБ и удаляя куски, когда все сообщения прочитаны. И если в таком журнале оказывается сообщение из неактивной очереди, часть журнала будет жить вечно. А если количество больших сообщение велико, то таких кусков журнала тоже будет велико.
Решений можно придумать массу, но так как вопрос с тегом RabbitMQ и больше нет вводных данных, то и ответ ограничен в вариантах. Вам больше виднее, что лучше подходит, но решение на RabbitMQ, кмк, самое простое, но и менее гибкое.
В идеале паблишер не должен знать про очереди, только про обменник куда посылать сообщения, это по сути граница разделения между разными частями системы. Например, в случае, если одни и те же данные будут нужны в двух сервисах, Вам придётся менять паблишера, что не есть хорошо.
Всё зависит от среды, но банально - HTTP запросом :-)
По комментарию в другом ответе могу сказать, что стоит попробовать NATS, так как получателей будет много, а недоставленные сообщения вообще хранить не надо.
В данном случае я бы рекомендовал, если и использовать RabbitMQ, то только для нотификации пользователя о новых данных. Но в таком случае всё усложняется для клиентского (два источника данных) и серверного кода (дополнительные компоненты, долгие коннекты, очереди).
Но, если очень хочется (наиболее простой вариант):
Создаётся один обменник типа fanout. При создании события продьюсер посылает в него сообщение. Каждый сервер, который принимает долгие коннекты и может отправить пользователю сообщение, подключается к этому обменнику со своей очередью, получает сообщения и рассылает их, если есть кому.
Чтобы не делать сложную систему, попробуйте (условно) раз в 10 секунд опрашивать БД на тему необработанных заявок, без необходимости создавать очереди на RabbitMQ. При ваших цифрах это выглядит оправданно.
deadsquirrel93, да, если очередь существует (и привязана к обменнику) в момент публикации сообщения, то сообщение в ней останется до того как потребитель запросит его (через subscription или basic_get, при условии что нет ограничивающих время политик).
Исправлю немного ответ выше, fanout это самый просто тип обменника и он может применяться вне зависимоти кластер это или одна нода, это зависит от задачи, если нужно "продублировать" сообщение во все очереди - он идеален для этого. Так же никто не мешает биндить один обменник на другой.
Даша Циклаури, то есть через всю эту систему Вы хотите сделать транзакционный канал обновления состояния клиента, интересная затея. По сути надо реализовать TCP уровня приложения. У меня не было подобного опыта, но возникает пара возможных путей:
1) У состояния есть версия (к примеру. таймстамп сервера, или просто увеличивающееся число, наподобии optimistic lock). Клиент его получает и запрос на изменени шлёт с текущей версией. На сервере, если версия отличается, то операция отклоняется и клиента просять обновить состояние). Но такое не сильно будет работать, когда допускается несколько параллельных сессий одного и того же клиента.
2) Клиент на каждый запрос генерит уникальный айди (UUID, например) и, если надо повторить то использует тот же идентификатор. Сервер держит список последних запросов за какой-то интервал времени и, если приходит дубликат, то отклоняет его.
Но в обоих случаях по сути решается проблема ненадёжного канала связи и неважно что стоит меджу сервисом_1 и _2.
Если переподключение пользователя и перезагрузка сервиса (отказ или обновление) влияют на суммарно малый процент от всех запросов, повтор запроса это не дорого, и есть возможность повлиять на клиентский код, то на мой взгляд тут не надо сильно стараться что-то сохранить, а просто повторить запрос с клиента, и тот же RPC (через RabbitMQ/NATS/Redis) вполне зайдёт. Плюсом это избавит от головной боли отладки, когда что-то не так с "состоянием".
Опишите тогда поподробней процесс взаимодействия пользователя и требования, например, если ответ готов, когда клиент ушёл, это надо держать в очереди до его возвращения? Клиент может подключиться к абсолютно любому серверу и выбор сервера случайный процесс? Чем больше требований к сохранению состояния, тем сложнее будет система. Как вариант хранить результат в БД (при отсылке удалять), а RPC использовать как реалтайм уведомление о готовности, и 99% времени именно он и будет работать.
Нет, для успешной отправки очередь не требуется. Возможно Вы начитались простых мануалов где всё создаётся из одного места. У меня, к сожалению, нет для Вас хорошего примера ещё, могу сослаться на свою статью на хабре, там можно увидеть, что обменники это необходимый инструмент.
Нет, в том то и дело, что клиент не должен знать названия очередей, так как, например, они могут быть автоматически сгенерированными в рамках одного подключения. В простых примерах в интернете обычно есть одна очередь и один обменник (даже с тем же именем), но это особо не отражает реальные бизнес-кейсы. Сами обменники могут быть разного типа и вести себя по-разному, для разных задач. Вы даже можете свой обменник в качестве плагина написать, чтобы решить какую-то специфическую задачу. В момент публикации по протоколу AMQP указывается именно обменник, а не очередь.
Возможно стоит посмотреть официальный мануал на эту тему - https://www.rabbitmq.com/channels.html