RabbitMQ. Частина 2. Розбираємось з Exchanges

Exchange - Обмінник або точка обміну. До нього надсилаються повідомлення. Exchange розподіляє повідомлення в одну чи кілька черг. Він маршрутизує повідомлення в чергу на основі створених зв'язків (bindings) між ним та чергою.

Exchange не є Erlang-процесом. З міркувань масштабованості exchange - Це рядок (посилання на модуль з кодом, де лежить логіка маршрутизації) у вбудованій базі даних мнезія. 1 тисячі обмінників будуть споживати всього 1МБ пам'яті.

Зміст

  • RabbitMQ. Частина 1. Introduction. Erlang, AMQP та RPC
  • RabbitMQ. Частина 2. Розбираємось з Exchanges
  • RabbitMQ. Частина 3. Розбираємося з Queues та Bindings
  • RabbitMQ. Частина 4. Розбираємося з тим що-небудь повідомлення та кадри
  • RabbitMQ. Частина 5. Продуктивність публікації та споживання повідомлень
  • RabbitMQ. Частина 6. Огляд модулів Federation та Shovel
  • RabbitMQ. Частина 7. Докладно про Connection та Chanel
  • RabbitMQ. Частина 8. RabbitMQ у .NET
  • RabbitMQ. Частина 9. Моніторинг

Direct Exchange

Direct exchange - використовується, коли потрібно доставити повідомлення до певних черг. Повідомлення публікується в обмінник із певним ключем маршрутизації і потрапляє у всі черги, пов'язані з цим обмінником аналогічним ключем маршрутизації. Ключ маршрутизації - це рядок. Пошук відповідності відбувається за допомогою перевірки рядків на еквівалентність.

Графічне подання потоку повідомлень:

RabbitMQ. Частина 2. Розбираємось з Exchanges

В rabbitmq існує поняття обмінник за замовчуванням. Це direct exchange без імені. Якщо застосовується обмінник за промовчанням, то повідомлення маршрутизуватиметься у чергу з іменем рівним ключу маршрутизації повідомлення.

Topic Exchange

Topic exchange – аналогічно direct exchange дає можливість здійснення вибіркової маршрутизації шляхом порівняння ключа маршрутизації. Але, в даному випадку, ключ задається за шаблоном. При створенні шаблону використовуються 0 або більше слів (літери AZ и az та цифри 0-9), розділених точкою, а також символи * и #.

  • * — може бути замінений на рівно 1 слово
  • # - може бути замінений на 0 або більше слів

Графічне подання потоку повідомлень:

RabbitMQ. Частина 2. Розбираємось з Exchanges

Починаючи з версії RabbitMQ 2.4.0 алгоритм маршрутизації для topic exchange став працювати до 145 разів швидше. Досягнули вони цього шляхом впровадження підходу trie implementation, який передбачає представлення шаблонів у вигляді структури дерева. Наприклад шаблони a.b.c, a.*.b.c, a.#.c и b.b.c будуть представлені наступною структурою:

RabbitMQ. Частина 2. Розбираємось з Exchanges

Пошук відповідності шаблону здійснюється, починаючи з кореня і слідуючи зверху донизу.

Особливості:

  • застосування цього обмінника може стати хорошим вибором для можливого майбутнього розвитку програми, т.к. шаблони завжди можна налаштувати так, щоб повідомлення публікувалося аналогічно direct exchange або fanout exchange
  • шаблони, які використовують * набагато швидше, ніж шаблони, які використовують #.
  • topic exchange повільніше direct exchange

Fanout Exchange

Fanout exchange - всі повідомлення доставляються у всі черги навіть якщо у повідомленні встановлено ключ маршрутизації.

Особливості:

  • RabbitMQ не працює з ключами маршрутизації та шаблонами що позитивно впливає продуктивність. Це найшвидший exchange;
  • всі споживачі повинні мати можливість обробляти всі повідомлення;

Графічне подання потоку повідомлень:

RabbitMQ. Частина 2. Розбираємось з Exchanges

Обмін заголовками

Headers exchange — надсилає повідомлення у зв'язані черги на основі порівняння пар (ключ, значення) властивості headers прив'язки та аналогічного властивості повідомлення. headers являє собою Dictionary<ключ, значение>.

Якщо до словника додати спеціальний ключ x-match зі значенням any, то повідомлення маршрутизується при частковому збігу пар (ключ, значення). Ця поведінка аналогічна оператору or.

var bindingArguments = new Dictinary<String, Object>();
bindingArguments.add("x-match", "any");

За замовчуванням ключ x-match містить значення all. Це означає, що повідомлення маршрутизується за повного збігу пар (ключ, значення). Ця поведінка аналогічна оператору and.

Графічне подання потоку повідомлень:

RabbitMQ. Частина 2. Розбираємось з Exchanges

Особливості:

  • додаткова гнучкість
  • додаткові накладні витрати на обчислення. Усі пари (ключ, значення) атрибуту headers повинні сортуватися на ім'я ключа перед обчисленням значень маршрутизації повідомлення. Повільніше, ніж інші типи exchange.

Consistent-Hashing Exchange

Цей обмінник є плагіном и не вбудований в RabbitMQ.

Consistent-hashing exchange (exchange з узгодженим хешуванням) – використовується, коли є кілька черг, які є потенційними одержувачами повідомлення, і коли потрібно збалансувати навантаження між ними. Зв'язок повідомлення з чергою відбувається за вагою (умовне строкове значення від 0 - n).

Еквівалентна вага черг - говорить про те, що в кожну чергу прийде приблизно однакова кількість повідомлень (кожне повідомлення буде розміщено лише в одну чергу). Повної гарантії рівномірного розподілу повідомлень немає.

Графічне подання потоку повідомлень:

RabbitMQ. Частина 2. Розбираємось з Exchanges

Hash обчислюється на основі ключа маршрутизації чи властивості headers повідомлення. Якщо всі повідомлення, що публікуються, мали різні ключі маршрутизації або headers, то розподіл відбуватиметься за вагою. Інакше буде використовуватися ключ маршрутизації або headers.

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

Комбінування обмінників (E2E)

Поведінка всіх обмінників можна комбінувати за допомогою зв'язку Exchange-to-Exchange (комбінування обмінників не входить до специфікації AMQP. Це розширення протоколу з боку RabbitMQ).

Графічне подання потоку повідомлень:

RabbitMQ. Частина 2. Розбираємось з Exchanges

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

Створення Exchange

Створення обмінника відбувається за допомогою синхронного RPC запит до сервера. Запит здійснюється за допомогою методу Exchange.Declare, що викликається з параметрами:

  • назва обмінника
  • тип обмінника
  • інші параметри

приклад створення exchange за допомогою RabbitMQ.Client:

//...
channel.ExchangeDeclare(
    exchange: "my_exchange",
    type: "direct",
    durable: "false",
    autoDelete: "false",
    arguments: null
);
//...

  • exchange - Назва обмінника, який ми хочемо створити. Назва має бути унікальною
  • type - Тип обмінника
  • durable - якщо встановити true, То exchange буде постійним. Він зберігатиметься на диску і зможе пережити перезапуск сервера/брокера. Якщо значення false, То exchange є тимчасовим і буде видалятися, коли сервер/брокер буде перезавантажено
  • autoDelete - Автоматичне видалення. Exchange буде видалено, коли будуть видалені всі пов'язані з ним черги
  • arguments - Необов'язкові аргументи. Найчастіше через аргументи задають alternative exchange (альтернативний обмінник). Якщо повідомлення не може пройти по початковому маршруту, його можна надіслати альтернативним обмінником для маршрутизації іншим шляхом.

RabbitMQ. Частина 2. Розбираємось з Exchanges

Якщо створення exchange можливосервер відправить клієнту синхронний RPC відповідь Exchange.DeclareOk. Якщо створення неможливо (відбулася відмова на запит Exchange.Declare), То канал закриється сервером за допомогою асинхронної команди Channel.Close і клієнт отримає виняток OperationInterruptedException, що міститиме код помилки та її опис.

Обмінник має бути створений перед публікацією повідомлень. Якщо ви опублікуєте повідомлення в якийсь неіснуючий обмінник RabbitMQ тихо видалить його.

Створення Exchange через графічний інтерфейс

Заходимо в панель адміністратора RabbitMQ під користувачем guest (username: guest та password: guest). Зверніть увагу, що користувач guest може підключатися лише з локального хоста. Тепер перейдемо на вкладку Exchanges і натиснемо на Add a new exchange. Заповнюємо властивості:

RabbitMQ. Частина 2. Розбираємось з Exchanges

Більшість властивостей була описана вище. Тут зазначимо, що якщо поставити Internal, то обмін можна буде використовувати тільки для E2E. Producer не зможе надсилати повідомлення на такий обмін.

Висновок

Під час розробки системи зручно описувати топологію маршрутизації за допомогою графа. Але як розпочати будувати граф варто виділити шляхи з великим трафіком, т.к. саме вони вимагають більш високу пропускну здатність (продуктивність). Далі можна класифікувати трафік. І вже потім розпочати побудову.

Якщо у побудованому графі існує кінцеве множиться ключів маршрутизації, варто подивитися в бік декількох fanout exchange, які 1:1 пов'язані з ключем маршрутизації. Пам'ятаємо, що fanout exchange найшвидший.

Якщо кількість маршрутів прагне нескінченності, то варто звернути увагу на topic exchange або, якщо шаблон не потрібен, можна вибрати direct exchnge, т.к. він швидше topic exchange.

Комбінації різних exchange повинна допомогти знайти правильну масштабовану конфігураціюяка відповідає як поточним, так і зростаючим вимогам системи.

Кількість exchange та черг має бути мінімально порівняно з кількістю маршрутів.

У наступній статті почнемо розбиратися докладніше з Queues та Bindings.

Посилання

Джерело: habr.com

Додати коментар або відгук