RabbitMQ та зв'язок між каналом та з'єднанням


176

У клієнта RabbitMQ Java є такі поняття:

  • Connection - підключення до екземпляра сервера RabbitMQ
  • Channel - ???
  • Пул потоків споживачів - пул потоків, які споживають повідомлення з черг сервера RabbitMQ
  • Черга - структура, що вміщує повідомлення в порядку FIFO

Я намагаюся зрозуміти відносини, і що ще важливіше , асоціації між ними.

  1. Я все ще не зовсім впевнений, що Channelтаке, крім того, що це та структура, яку ви публікуєте та споживаєте, і що вона створена з відкритого зв'язку. Якщо хтось міг би пояснити мені, що собою являє "Канал", це може допомогти прояснити кілька речей.
  2. Які стосунки між каналом та чергою? Чи може той же Канал використовуватись для спілкування з кількома Чергами, або це має бути 1: 1?
  3. Які стосунки між Чергою та Споживчим Басейном? Чи можуть декілька споживачів підписатися на одну і ту ж чергу? Чи може один і той же споживач споживати кілька черг? Або відносини 1: 1?

Заздалегідь дякую за будь-яку допомогу тут!


Відповіді на це запитання змусили мене повідомити про це питання з клієнтом голангом, а не задавати його тут.
Брюс Адамс

Канал - це логічна концепція, яка використовується для мультиплексування єдиного фізичного TCP-з'єднання між клієнтом і вузлом. Номер каналу включений в заголовок повідомлення кадру AMQP.
ymas

Відповіді:


196
  1. A Connectionявляє собою реальне TCP-з'єднання з брокером повідомлень, тоді як a Channel- це віртуальне з'єднання (AMQP-з'єднання) всередині нього. Таким чином ви можете використовувати стільки (віртуальних) з'єднань, скільки хочете, щоб усередині програми не перевантажуючи брокера TCP-з'єднаннями.

  2. Ви можете використовувати його Channelдля всього. Однак якщо у вас є кілька потоків, Channelдля кожного потоку пропонується використовувати різні .

    Безпека потоку каналів у посібнику API для клієнта Java :

    Екземпляри каналів безпечні для використання декількома потоками. Запити на канал серіалізовані, лише один потік може одночасно виконувати команду на каналі. Незважаючи на це, додатки повинні віддавати перевагу використанню каналу на один потік, а не обмінюватися тим самим каналом на кілька потоків.

    Прямого зв’язку між Channelі Queue. A Channelвикористовується для надсилання команд AMQP брокеру. Це може бути створення черги чи подібне, але ці поняття не зв'язані між собою.

  3. Кожен Consumerпрацює у власному потоці, виділеному з пулу споживчих ниток. Якщо на одній черзі підписано декілька споживачів, брокер використовує круговий обмін, щоб розподіляти повідомлення між ними однаково. Дивіться підручник другий: "Робочі черги" .

    Також можливо приєднати те саме Consumerдо кількох Черг. Ви можете зрозуміти споживачів як зворотній зв'язок. Вони називаються щоразу, коли повідомлення надходить у чергу, на яку зобов'язаний споживач. У випадку з клієнтом Java у кожного споживача є метод handleDelivery(...), який представляє метод зворотного виклику. Зазвичай ви робите це підклас DefaultConsumerта переопределення handleDelivery(...). Примітка. Якщо ви приєднаєте один і той же екземпляр споживача до кількох черг, цей метод буде викликаний різними потоками. Тому подбайте про синхронізацію, якщо це необхідно.


4
Просто додати з документації: Відкликання викликів для споживачів надсилається по потоку, окремому від потоку, яким керується з'єднання. Це означає, що Споживачі можуть безпечно викликати способи блокування на З'єднанні або каналі, такі як queueDeclare, txCommit, basicCancel або basicPublish. Кожен канал має свою диспетчерську нитку. Для найпоширеніших випадків використання одного споживача на канал це означає, що споживачі не затримують інших споживачів. Якщо у вас є кілька споживачів на канал, майте на увазі, що тривалий Споживач може перестати надсилати зворотні дзвінки іншим споживачам на цьому каналі.
Філіп

1
Якщо ви приєднаєте один і той самий споживчий екземпляр до кількох черг з одного каналу, це означатиме, що зворотні виклики надсилаються в одному потоці. У такому випадку вам не знадобиться синхронізація, чи не так?
Філіп

Чи можу я використовувати лише одне з'єднання та використовувати пул каналів замість пулу з'єднань? Чи вплине це на пропускну здатність публікації повідомлень?
qeek

4
Я думаю, що ця посилання на API API Java Client застаріла, і фактично сьогоднішня посилання прямо суперечить цитаті у цій відповіді. Сьогоднішня посилання говорить: "Екземпляри каналів не повинні ділитися між потоками".
Едвін Далорцо

1
@EdwinDalorzo - схоже, хто первісно написав документацію, не повністю зрозумів дихотомію канального зв'язку. Фундаментальна архітектура AMQP 0.9.1 по-справжньому трактує канал як сеанс, тому різні теми, що обмінюються сеансом, насправді - це нісенітниця. Я здогадуюсь, що це причина змін.
theMayer

53

Тут добре корисне розуміння того, що робить протокол AMQP "під капотом". Я б запропонував, що документація та API, які AMQP 0.9.1 обрав для розгортання, роблять це особливо заплутаним, тому саме питання є таким, з яким багатьом людям доводиться боротися.

TL; DR

З'єднання є фізичним переговорами TCP сокета з сервером AMQP. Належно реалізовані клієнти матимуть один із них на додаток, безпечний для потоків, доступний між потоками.

Канал є один сеанс додатки на зв'язку. У потоці буде один або більше таких сеансів. AMQP архітектура 0.9.1 полягає в тому, що їх не слід ділити між потоками, і їх слід закрити / знищити, коли нитка, яка її створила, закінчиться з нею. Вони також закриваються сервером, коли трапляються різні порушення протоколу.

Споживач є віртуальною конструкцію , яка представляє наявність «поштову скриньку» на певному каналі. Використання споживача повідомляє брокеру проштовхувати повідомлення з певної черги до кінцевої точки каналу.

Факти підключення

По-перше, як правильно вказали інші, з'єднання - це об'єкт, який представляє фактичне TCP-з'єднання з сервером. Підключення визначаються на рівні протоколу в AMQP, і все спілкування з брокером відбувається через одне або більше з'єднань.

  • Оскільки це фактичне TCP-з'єднання, у нього є IP-адреса та порт №.
  • Параметри протоколу узгоджуються на основі клієнта як частина налаштування з'єднання (процес, відомий як рукостискання .
  • Він призначений для довгожиття ; мало випадків, коли закриття з'єднання є частиною проекту протоколу.
  • З точки зору OSI, він, ймовірно, знаходиться десь близько 6 рівня
  • Серцебиття можна налаштувати для контролю стану з'єднання, оскільки TCP не містить нічого саме по собі для цього.
  • Найкраще мати спеціальний потік, який керує зчитуванням і записом у базовий сокет TCP. Більшість, якщо не всі, клієнти RabbitMQ роблять це. У зв'язку з цим вони, як правило, безпечні для ниток.
  • По відношенню, з'єднання "дорого" створити (завдяки рукостисканню), але практично кажучи, це насправді не має значення. Для більшості процесів дійсно знадобиться лише один об’єкт з'єднання. Але ви можете підтримувати з'єднання в пулі, якщо вам здається, що вам потрібна більша пропускна здатність, ніж може забезпечити один потік / розетка (малоймовірно при сучасній обчислювальній технології).

Факти каналу

Канал є додатком сеансу , який відкритий для кожної частини вашого застосування , щоб спілкуватися з RabbitMQ брокером. Він працює над одним з'єднанням і представляє сеанс з брокером.

  • Оскільки він представляє логічну частину логіки програми, кожен канал зазвичай існує у власному потоці.
  • Зазвичай усі канали, відкриті вашим додатком, матимуть спільне з'єднання (це легкі сеанси, які працюють над версією з'єднання). З'єднання захищені потоком, тому це нормально.
  • Більшість операцій AMQP відбувається по каналах.
  • З точки зору рівня OSI, канали, ймовірно, є навколо рівня 7 .
  • Канали розраховані на тимчасові ; частина дизайну AMQP полягає в тому, що канал, як правило, закритий у відповідь на помилку (наприклад, повторне оголошення черги з різними параметрами перед видаленням існуючої черги).
  • Оскільки вони є тимчасовими, ваші програми не повинні об'єднувати канали.
  • Сервер використовує ціле число для ідентифікації каналу. Коли потік, що керує з'єднанням, отримує пакет для певного каналу, він використовує це число, щоб повідомити брокеру, якому каналу / сесії належить пакет.
  • Як правило, канали не є безпечними для потоків, оскільки не має сенсу ділитися ними між потоками. Якщо у вас є інший потік, який потребує використання брокера, потрібен новий канал.

Факти споживачів

Споживач - це об'єкт, визначений протоколом AMQP. Це ні канал, ні з'єднання, а натомість те, що ваша конкретна програма використовує як "поштову скриньку" для видалення повідомлень.

  • "Створення споживача" означає, що ви повідомляєте брокеру (використовуючи канал через з'єднання ), що ви хочете, щоб повідомлення, що надсилаються вам по цьому каналу. У відповідь брокер зареєструє, що у вас є споживач на каналі, і почне надсилати вам повідомлення.
  • Кожне повідомлення, натиснуте на з'єднання, посилається як на номер каналу, так і на номер споживача . Таким чином, потік управління зв’язком (в даному випадку в рамках Java API) знає, що робити з повідомленням; Тоді потік обробки каналів також знає, що робити з повідомленням.
  • Реалізація споживачів має найбільшу кількість варіацій, тому що це буквально залежно від застосування. У моєму виконанні я вирішив виконувати завдання щоразу, коли повідомлення надходило через споживача; таким чином, у мене був потік, що керує з'єднанням, потік, що управляє каналом (і розширенням, споживачем), і один або більше потоків завдань для кожного повідомлення, доставленого через споживача.
  • Закриття з'єднання закриває всі канали з'єднання. Закриття каналу закриває всіх споживачів каналу. Також можливо скасувати споживача (без закриття каналу). Існують різні випадки, коли є сенс робити будь-яку з трьох речей.
  • Як правило, реалізація споживача в клієнті AMQP виділяє споживачеві один виділений канал, щоб уникнути конфліктів з діяльністю інших потоків або коду (включаючи публікацію).

З точки зору того, що ви маєте на увазі під пулом потоків споживачів, я підозрюю, що клієнт Java робить щось подібне до того, що я запрограмував, щоб мій клієнт (мій був заснований на клієнті .Net, але сильно модифікований).


1
"канали не повинні бути об'єднані", ось що я шукаю
ospider

"Оскільки вони є тимчасовими, ваші програми не повинні об'єднувати канали." - чи можете ви уточнити, як ви прийшли до цього висновку, будь ласка. Документи рекомендують об'єднати канали, якщо "один канал на нитку" використовує занадто багато ресурсів, дивіться тут: rabbitmq.com/channels.html#resource-usage
ymas

@ymas - Документація, яку ви посилаєтесь, є умоглядною, і на мою думку, поганою настановою. Я читаю вихідний код та специфікацію протоколу. Канал не слід об'єднувати, періодично. Крім того, один канал на нитку - це керівництво, засноване на цьому самому принципі. Якщо ви виявите, що у вас стільки відкритих каналів, що сервер обмежений ресурсами, вам потрібно переоцінити свою архітектуру (тобто перейти на схему з високою доступністю та / або зменшити паралельність).
theMayer

21

Я знайшов цю статтю, яка пояснює всі аспекти моделі AMQP, з яких канал - це один. Я вважаю це дуже корисним у закріпленні свого розуміння

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

Деякі програми потребують декількох підключень до брокера AMQP. Однак небажано тримати багато з’єднань TCP одночасно відкритими, оскільки це споживає системні ресурси та ускладнює налаштування брандмауерів. Підключення AMQP 0-9-1 мультиплексовані з каналами, які можна розглядати як "легкі з'єднання, які розділяють одне з'єднання TCP".

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

Комунікація на певному каналі повністю відокремлена від зв'язку на іншому каналі, тому кожен метод AMQP також містить номер каналу, який клієнти використовують, щоб з'ясувати, для якого каналу використовується метод (і, наприклад, для якого обробника подій потрібно викликати, наприклад) .


4

Існує зв’язок між тим, як TCP-з'єднання може мати декілька каналів .

Канал : це віртуальне з'єднання всередині з'єднання. Коли ви публікуєте або використовуєте повідомлення з черги - це все робиться по каналу. Підключення : це з'єднання TCP між вашою програмою та брокером RabbitMQ.

У архітектурі з декількома нитками може знадобитися окреме з'єднання на кожну нитку. Це може призвести до недовикористання TCP-з'єднання, а також додасть накладні витрати в операційну систему, щоб встановити стільки TCP-з'єднань, які йому потрібні протягом пікового часу мережі. Продуктивність системи може бути різко знижена. Ось тут канал стане в нагоді, він створює віртуальне з'єднання всередині TCP-з'єднання. Це прямо зменшує накладні витрати на ОС, також дозволяє нам виконувати асинхронні операції більш швидким, надійним і одночасно. введіть тут опис зображення

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.