RabbitMQ и связь между каналом и соединением

RabbitMQ Java-клиент имеет следующие понятия:

  • Connection - подключение к экземпляру сервера RabbitMQ
  • Channel -
  • Пул потоков потребителей - пул потоков, которые потребляют сообщения с очередей серверов RabbitMQ.
  • Очередь - структура, содержащая сообщения в порядке FIFO

Я пытаюсь понять отношения, и, что более важно,, ассоциации между ними.

  • Я все еще не совсем уверен, что такое Channel, за исключением того факта, что это структура, которую вы публикуете и потребляете, и что она создана из открытого соединения. Если кто-то может объяснить мне, что представляет собой "Канал", это может помочь прояснить некоторые моменты.
  • Какова связь между каналом и очередью? Может ли тот же канал использоваться для связи с краткими очередями или он должен быть 1:1?
  • Какова связь между очередью и пулом пользователей? Можно ли подписывать несколько потребителей на одну и ту же очередь? Можно ли использовать несколько очередей одним и тем же потребителем? Или это соотношение 1:1?

Заранее благодарим за помощь!

Ответ 1

  • A Connection представляет реальное TCP-соединение с брокером сообщений, тогда как Channel - это виртуальное соединение (соединение AMPQ) внутри него. Таким образом вы можете использовать как можно больше (виртуальных) соединений внутри вашего приложения, не перегружая брокера TCP-соединениями.

  • Вы можете использовать один Channel для всех. Однако, если у вас несколько потоков, для каждого потока предлагается использовать другой Channel.

    Безопасность потоков каналов в API API Java Client:

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

    Прямой связи между Channel и Queue нет. A Channel используется для отправки команд AMQP брокеру. Это может быть создание очереди или аналогичной, но эти понятия не связаны друг с другом.

  • Каждый Consumer работает в своем собственном потоке, выделенном из пула потребительских потоков. Если несколько потребителей подписываются на одну и ту же очередь, брокер использует циклический доступ для равномерного распределения сообщений между ними. См. Учебное пособие два: "Рабочие очереди" .

    Также можно присоединить те же Consumer к нескольким очередям. Вы можете понимать Потребителей как обратные вызовы. Они называются каждый раз, когда сообщение поступает в очередь, к которой привязан Потребитель. В случае с Java-клиентом у каждого потребителя есть метод handleDelivery(...), который представляет метод обратного вызова. Что вы обычно делаете, это подкласс DefaultConsumer и переопределить handleDelivery(...). Примечание. Если вы присоедините один и тот же экземпляр пользователя к нескольким очередям, этот метод будет вызываться разными потоками. Поэтому при необходимости позаботьтесь о синхронизации.

Ответ 2

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

https://www.rabbitmq.com/tutorials/amqp-concepts.html

Некоторым приложениям требуется несколько подключений к брокеру AMQP. Тем не менее, нежелательно одновременно открывать много соединений TCP, потому что это расходует системные ресурсы и затрудняет настройку брандмауэров. Соединения AMQP 0-9-1 мультиплексируются с каналами, которые можно рассматривать как "легкие соединения, которые используют одно TCP-соединение".

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

Связь на определенном канале полностью отделена от связи на другом канале, поэтому каждый метод AMQP также содержит номер канала, который клиенты используют для определения того, для какого канала используется метод (и, следовательно, какой обработчик события необходимо вызвать, например).

Ответ 3

Полезное концептуальное понимание того, что протокол AMQP делает "под капотом", здесь полезен. Я бы предположил, что документация и API, которые AMQP 0.9.1 выбрал для развертывания, делают это особенно запутанным, поэтому сам вопрос - это тот, с которым приходится бороться много людей.

TL; DR

Соединение - это физический согласованный TCP-сокет с сервером AMQP. У правильно реализованных клиентов будет одно из этих приложений, потокобезопасное, разделяемое между потоками.

Канал - это один сеанс приложения в соединении. В потоке будет один или несколько из этих сеансов. Архитектура AMQP 0.9.1 заключается в том, что они не должны быть разделены между потоками и должны быть закрыты/уничтожены, когда поток, который его создал, завершен. Они также закрываются сервером при возникновении различных нарушений протокола.

Потребитель - это виртуальная конструкция, которая представляет наличие "почтового ящика" на определенном канале. Использование потребителя указывает брокеру направить сообщения из определенной очереди в конечную точку этого канала.

Факты о соединении

Во-первых, как правильно указали другие, соединение представляет собой объект, который представляет фактическое TCP-соединение с сервером. Соединения указаны на уровне протокола в AMQP, и вся связь с брокером происходит по одному или нескольким соединениям.

  • Поскольку это фактическое TCP-соединение, оно имеет IP-адрес и порт #.
  • Параметры протокола согласовываются для каждого клиента в рамках настройки соединения (процесс, известный как рукопожатие.
  • Он рассчитан на долговечность; существует несколько случаев, когда закрытие соединения является частью конструкции протокола.
  • С точки зрения OSI, он, вероятно, находится где-то около уровня 6
  • Heartbeats можно настроить для контроля состояния соединения, поскольку TCP не содержит ничего в себе и для этого.
  • Лучше всего, чтобы выделенный поток управлял чтением и записью в основной сокет TCP. Большинство, если не все, клиенты RabbitMQ делают это. В этом отношении они, как правило, являются потокобезопасными.
  • Относительно говоря, соединения "дороги" для создания (из-за рукопожатия), но, на самом деле, это действительно не имеет значения. Для большинства процессов действительно нужен только один объект соединения. Но вы можете поддерживать соединения в пуле, если вы обнаружите, что вам требуется больше пропускной способности, чем может обеспечить один поток/сокет (маловероятный с использованием современных вычислительных технологий).

Факты канала

Канал - это сеанс приложения, который открывается для каждой части вашего приложения для связи с брокером RabbitMQ. Он работает по одному соединению и представляет сеанс с брокером.

  • Поскольку он представляет логическую часть логики приложения, каждый канал обычно существует в своем потоке.
  • Как правило, все каналы, открытые вашим приложением, будут иметь одно соединение (это легкие сеансы, которые работают поверх соединения). Соединения являются потокобезопасными, поэтому все в порядке.
  • Большинство операций AMQP происходит по каналам.
  • С точки зрения уровня OSI каналы, вероятно, находятся вокруг уровня 7.
  • Каналы рассчитаны на переходные процессы; часть дизайна AMQP заключается в том, что канал обычно закрыт в ответ на ошибку (например, повторное объявление очереди с разными параметрами перед удалением существующей очереди).
  • Поскольку они временны, каналы не должны объединяться в ваше приложение.
  • Для идентификации канала сервер использует целое число. Когда поток, управляющий соединением, получает пакет для определенного канала, он использует этот номер, чтобы сообщить брокеру, к какому каналу/сеансу принадлежит пакет.
  • Каналы обычно не являются потокобезопасными, так как не имеет смысла делиться ими между потоками. Если у вас есть другой поток, который должен использовать брокера, необходим новый канал.

Факты о покупателе

Потребитель - это объект, определенный протоколом AMQP. Это ни канал, ни соединение, а не то, что ваше конкретное приложение использует как "почтовый ящик" для сортировки сообщений.

  • "Создание потребителя" означает, что вы сообщаете брокеру (используя канал через соединение), что вы хотели бы получить сообщения, направленные вам по этому каналу. В ответ брокер зарегистрирует, что у вас есть потребитель на канале, и начинайте нажимать на вас сообщения.
  • Каждое сообщение, нажимаемое на соединение, будет ссылаться как на номер канала, так и на потребительский номер. Таким образом, поток управления подключением (в данном случае, в Java API) знает, что делать с сообщением; то поток обработки канала также знает, что делать с сообщением.
  • Потребительская реализация имеет самую широкую вариацию, поскольку она в буквальном смысле относится к конкретным приложениям. В моей реализации я решил отменить задачу каждый раз, когда сообщение прибыло через потребителя; таким образом, у меня был поток, управляющий соединением, поток, управляющий каналом (и по расширению, потребитель), и один или несколько потоков задач для каждого сообщения, доставляемого через пользователя.
  • Закрытие соединения закрывает все каналы в соединении. Закрытие канала закрывает всех потребителей на канале. Также можно отменить пользователя (без закрытия канала). Существуют различные случаи, когда имеет смысл делать любую из трех вещей.
  • Как правило, реализация потребителя в клиенте AMQP будет выделять одному выделенному каналу потребителю, чтобы избежать конфликтов с действиями других потоков или кода (включая публикацию).

С точки зрения того, что вы подразумеваете под пулом потребительских потоков, я подозреваю, что клиент Java делает что-то похожее на то, что я запрограммировал для моего клиента (мой был основан на клиенте.Net, но сильно модифицирован).