Руководство по созданию канала RabbitMQ - PullRequest
9 голосов
/ 15 апреля 2011

Я пишу простой класс, который мои приложения будут использовать для отправки и получения сообщений с использованием RabbitMQ. Я прочитал столько How-Tos, постов в блогах, официальных документов и тому подобного о RabbitMQ, сколько смог найти. В большинстве примеров показано использование соединения и канала, заключенных в блок using, и противоречат им, говоря, что вы, вероятно, должны реализовать их как одиночный. В частности, касательно канала, я видел комментарии о том, что у вас не должно быть более одного потока, использующего один канал одновременно.

Я пишу свою библиотеку на c #. это одиночный узел со статическим соединением, подключенным в первом экземпляре.

Я думал сделать то же самое для канала, но я намерен использовать одну и ту же библиотеку, чтобы разрешить публикацию / подписку на несколько обменов / очередей. Как публикация, так и подписка могут выполняться из нескольких потоков.

И, наконец, мой вопрос: Как мне реализовать создание каналов? За сообщение? Есть ли у каждого потребителя уникальный частный канал, издатель синхронизирует доступ к одному уникальному каналу? Вы ловите мой дрейф. Пожалуйста, имейте в виду, что я собираюсь использовать один сервер с несколькими десятками потребителей / издателей, не намного больше.

Спасибо!

Ответы [ 4 ]

6 голосов
/ 24 июля 2013

Редактировать (2016-1-26): Каналы НЕ являются потокобезопасными .Документация по этому вопросу изменилась в период с апреля и мая 2015. Новый текст:

Экземпляры канала не должны совместно использоваться потоками.Приложения должны предпочитать использовать канал для каждого потока, а не использовать один и тот же канал для нескольких потоков.Хотя некоторые операции над каналами безопасны для одновременного вызова, некоторые - нет, и это приведет к неправильному чередованию кадров в проводе.Совместное использование каналов между потоками также будет мешать * Подтверждениям издателя.

По вашему вопросу звучит так, будто у вас нет предопределенного фиксированного количества потоков, которые в основном публикуют / подписываются на RabbitMQ (в которомВ этом случае вы могли бы рассмотреть возможность создания канала как часть инициализации потока или использования ThreadLocal<IModel>).

Если параллельные операции RabbitMQ редки или размеры сообщений всегда малы, вам может быть не просто написатьlock(channel) вокруг всех ваших операций RabbitMQ pub / sub.Если вам нужно, чтобы несколько запросов передавались с чередованием - для этого в первую очередь нужны каналы - используя произвольные потоки, вы можете создать пул каналов , например ConcurrentQueue<IModel>, где вы ставите в очередьнеиспользуемые каналы и Dequeue на время, когда они вам нужны. Создание канала занимает очень мало времени , и из тестов производительности у меня возникает ощущение, что процесс создания канала не затрагивает никакой сетевой операции ввода-вывода, т.е. кажется, что канал получает автоматическисозданный на сервере RabbitMQ при первом использовании клиентом.


OLD (до 2016-1-26): в настоящее время в основном устарели детали реализации Java и .net:

Re: каналы и несколько потоков, что немного сбивает с толку из-за его зависимости от реализации.

Реализация Java : Каналы являются потокобезопасными :

Экземпляры канала безопасны для использования несколькими потоками.

Но :

подтверждает, что это не такобрабатывается правильно, когда канал используется несколькими потоками

.net реализация : Каналы не являются поточно-безопасными :

Если более чем одному потоку необходим доступ к конкретным экземплярам IModel, tПриложение должно принудительно применять взаимное исключение.

Симптомы неправильной сериализации операций IModel включают, но не ограничиваются,

• неверные последовательности кадров, отправляемые по проводам

• NotSupportedExceptions выдается ...

Таким образом, в дополнение к полезному ответу Робина, который применяется независимо от того, является ли он потокобезопасным, в реализации .net, вы не можете просто поделитьсясоединение .

3 голосов
/ 16 апреля 2011

Это разъясняет внутренности AQMP. В настоящее время мое понимание таково: О. Я могу держать одно, общее, TCP-соединение с сервером из каждого приложения (как статический общий ресурс) Б. Мне следует либо создать канал для каждой «задачи» (один для прослушивания очереди X, другой для публикации для обмена Y и т. Д., Предполагая, что эти «задачи» могут выполняться параллельно) C. Или я могу использовать один канал для всего в пределах одного приложения, при этом гарантируя, что доступ к нему синхронизирован - используя некоторый механизм блокировки, предполагая, что фактическое время, в течение которого канал используется (заблокировано), относительно очень короткое.

Спасибо.

2 голосов
/ 14 мая 2011

Вы правы, что канал НЕ является потокобезопасным и не должен быть доступен более чем одному потоку.

Если вы планируете использовать разные очереди, вы можете иметь несколько очередей с одним каналом.Но если вы планируете несколько обменов (не знаете, зачем вам здесь больше одного), вы будете вынуждены либо отслеживать несколько обменов и каналов в вашем синглтоне, либо перекладывать эту ответственность на абонентов.

Я бы собрал ваш синглтон таким образом, чтобы он имел шаблон наблюдателя, и содержал там весь материал RabbitMQ со ссылками на ваших абонентов.Затем вам также необходимо выполнить маршаллизацию вызовов для одного потока, который имеет дело с этим, или вы можете рисковать проблемами с объектами канала.

2 голосов
/ 15 апреля 2011

Я не могу комментировать особенности реализации C #, но это может помочь узнать, что каналы Amqp предназначены для совместного использования одного TCP-соединения, то есть для включения мультиплексирования.Один канал может отправлять только одно или получать одно сообщение одновременно, но соединение может получать сообщения по разным каналам одновременно.Если у вас есть 2 больших файла объемом 1 ГБ, которые вы отправляете через Amqp одному потребителю, возможно, что сообщения будут разбиты на куски по 10 Кб и отправлены с чередованием.Вы можете манипулировать размером сообщения Amqp по умолчанию при настройке соединения, это имеет отношение к тому, возможны ли и когда возможны чередования;AFAIK эта функция предназначена для предотвращения голодания, когда несколько потребителей совместно используют соединение и один потребитель получает большие сообщения.

HTH.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...