Налаштування NATS з JetStream і кластеризацією для продакшену

Повідомлення губляться під навантаженням, а черга зростає швидше, ніж її встигають розбирати? Ми налаштовуємо NATS з JetStream і кластеризацією під ключ: відмовостійкий обмін даними між сервісами без ручного втручання. Скорочуємо простої та обсяг втрачених повідомлень, супровід беремо на себе.
Часті запитання

Чому NATS втрачає повідомлення під навантаженням

На стенді NATS тримає потік рівно, тому перший пік у продакшені виглядає як загадка: частина повідомлень просто не доходить. У логах відправника — тиша, у метриках — сплеск відмов, а в черзі залишаються діри, які потім відновлюють звіркою із зовнішнім джерелом.

Втрата повідомлень складається з трьох причин: розрив з’єднання в момент перемикання вузла, переповнення черги в повільного споживача й відсутність підтверджень на боці відправника.

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

Якщо повторне надсилання й підтвердження не налаштовані, ці повідомлення губляться мовчки, без помилки на клієнті. Той самий механізм дає дублі, коли повтор увімкнено, але обробник не ідемпотентний: одна подія проходить двічі й ламає стан.

Друге джерело — затримки доставки й переповнення черги. Коли споживач не встигає, потік зростає до ліміту зберігання, і далі або спрацьовує політика витіснення старих записів, або відправник отримує відмову на запис.

На піках це виглядає як рваний потік: частина подій приходить із запізненням, частина зникає, а черга відновлюється ривком і добиває обробник відкладеною пачкою.

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

Що дає відмовостійкий кластер обміну повідомленнями

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

  • Відмова вузла не зупиняє потік. Кворум із трьох вузлів зберігає запис, коли одна машина випадає: публікація й підписка йдуть через живі вузли, клієнти перепідключаються самі. Час відновлення потоку — секунди замість простою сервісу.

  • Гарантія доставки задається явно. Повідомлення лежать на диску до підтвердження обробки, тому перезапуск сервісу-отримувача не призводить до втрати. Повторні обробки обмежені дедуплікацією й видимі в метриках, а не під час розбору інциденту.

  • Пікове навантаження не перетворюється на відмови. Якщо публікація йде швидше за обробку, різниця осідає в буфері зберігання, а не в помилках на вході — сервіс залишається доступним на сплеску.

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

  • Межі навантаження задані заздалегідь. Ліміти на отримувача й розділення потоків за призначенням не дають одному сервісу забрати ресурси в інших — деградація залишається локальною.

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

Режими NATS: потік, черга й постійне сховище

Режими NATS вирішують різні завдання, і вибір між ними визначається одним питанням: що має статися з повідомленням, якщо отримувач на момент відправлення недоступний. Базовий режим віддає подію всім підписникам теми відразу й ніде її не зберігає.

Черга робіт розподіляє потік між екземплярами сервісу — повідомлення йде рівно одному виконавцю. Постійне сховище JetStream записує потік на диск і дозволяє перечитати його після перезапуску.

Варіант Коли підходить Обмеження
Потокова доставка за темою Живі метрики, події інтерфейсу, скидання кешу Немає зберігання: підписник недоступний — повідомлення втрачено
Черга робіт Фонові завдання, розбір черги пулом виконавців Один обробник на повідомлення; повтор при збої організовується окремо
Постійне сховище (JetStream) Замовлення, платежі, аудит, обмін між сервісами Потребує диска й налаштованої політики зберігання, вища затримка

Вибір підказує сам характер даних: те, втрату чого можна пережити, іде за темою без зайвих накладних витрат; те, що потребує повторної обробки, — через JetStream із підтвердженням доставки.

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

Сховище вмикають точково, лише для потрібних тем, щоб не платити диском за весь трафік. Ліміт за віком або обсягом задається політикою зберігання — потік перестає зростати, а повторна обробка після збою залишається можливою.

Як ми розгортаємо кластер: етапи робіт

Кластер NATS збирається не за типовою інструкцією, а під конкретний профіль обміну: одному сервісу важлива кожна заявка, інший публікує телеметрію з допустимими втратами.

Порядок робіт у нас фіксований — він дозволяє ловити помилки топології на стенді, а не тоді, коли черга вже стала.

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

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

  3. Налаштування кластера. Розгортаємо вузли, об’єднуємо в кластер, вмикаємо JetStream, задаємо кворум, права доступу й шифрування трафіку між вузлами. Підключаємо метрики й оповіщення щодо відставання споживачів.

  4. Перевірка відмовою. Гасимо вузли по одному й парами: дивимося перевибори лідера, час відновлення, доступність публікації й підписки, відсутність дублів і втрат. На виході — заміри, а не обіцянки.

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

  6. Супровід. Стежимо за здоров’ям кластера, планово оновлюємо версії, розширюємо при зростанні навантаження, розбираємо інциденти з вашою командою.

Конфігурації, схеми й регламенти на виході

Артефакти передаємо не «архівом на згадку», а робочим комплектом: будь-яку з перелічених сутностей ваша команда зможе прочитати, змінити й розгорнути без нас.

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

  • Конфігурації вузлів — файли налаштувань кожного вузла з поясненнями щодо ключових параметрів: ліміти сховища, вікна зберігання повідомлень, таймаути, поведінка при втраті кворуму.
  • Схема кластера — топологія маршрутів, зони відмови, точки балансування, порядок додавання й виведення вузла на обслуговування.
  • Схема тем і підписок — карта потоків і черг: хто публікує, хто читає, які групи підписників ділять навантаження, де увімкнено повторне відтворення.
  • Політики прав доступу — за обліковими записами й просторами: хто має право публікувати, хто лише читати, кому закритий адміністративний контур, як видаються й відкликаються ключі.
  • Регламент експлуатації — планові роботи, контроль зростання сховища, ротація логів, порядок оновлення вузлів без зупинки обміну.
  • Інструкції з відновлення — сценарії на випадок втрати вузла або зони: що знімається з резерву, у якій послідовності піднімається, як перевіряється цілісність.
  • Моніторинг і оповіщення — набір метрик і порогів, при яких черговий отримує сигнал раніше, ніж проблема дійде до бізнес-логіки.
  • Передача знань — розбір з вашими інженерами по кожному артефакту, щоб команда вела систему самостійно.

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

Кейс: кластер NATS замість самописної черги

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

На піках таблиця впиралася в конкуренцію за рядки, завдання дублювалися, частина подій зникала без сліду — розбір такого інциденту займав вечір і вимагав ручної звірки з логами сервісів.

Що було до

Частка втрачених повідомлень у години пік сягала 0,3–0,5% від потоку, і в цих відсотках опинялися підтвердження оплати. Відновлення вузла після падіння займало близько 40 хвилин: воркери не перерозподіляли завдання самі, черговий піднімав їх руками.

Ручних втручань набиралося 8–12 на місяць — кожне відривало інженера від планових завдань і зсувало терміни.

Що зробили

Розгорнули кластер NATS з JetStream: потоки з дисковою персистентністю й реплікацією на кілька вузлів, споживачі з явним підтвердженням доставки й повторною видачею при помилці обробника.

Обробники зробили ідемпотентними за ключем події, щоб повтор був безпечний, а розбір «завислих» завдань замінили на автоматичну повторну видачу за таймаутом.

Що стало

На критичному потоці підтверджень оплати втрати повідомлень — нуль, включно з піковими вікнами. Вузол повертається в стрій менш ніж за хвилину: споживачі перепідключаються до живих реплік самі, ручний підйом більше не потрібен.

Втручання чергового скоротилися до планових оновлень, а завислі завдання видно в метриках потоку, а не з’ясовуються за скаргами.

Окремий ефект — передбачуваність відкату: стан черги зберігається на диску, тому перезапуск сервісу не означає втрату накопиченого потоку.

Чим кластер NATS відрізняється від одиночного брокера

Одиночний вузол NATS — один процес і одне сховище: поки він живий, публікація й підписка йдуть із мінімальною затримкою, конфігурація читається з одного файлу, а експлуатація зводиться до перезапуску служби. Точка відмови рівно одна, і вона збігається з точкою зупинки всього обміну між сервісами.

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

Але якщо випадуть два вузли з трьох, запис стане до повернення третього — усвідомлена плата за узгодженість даних.

Варіант Коли підходить Обмеження
Одиночний вузол Розробка, тестові контури, внутрішні завдання без вимог до безперервності Відмова вузла зупиняє обмін, оновлення потребує простою, незакомічені повідомлення губляться
Кластер із трьох вузлів Продакшен, де публікація не повинна перериватися Потрібен кворум: два вузли з трьох, що випали, блокують запис, складніша конфігурація маршрутів
Кластер із реплікацією потоків Сценарії, де втрата повідомлення неприпустима: платежі, завдання, події замовлень Затримка на підтвердження запису й у рази більший обсяг сховища

В експлуатації різниця не менша: кластеру потрібні узгоджені конфігурації, контроль маршрутів і реплікації, рознесення вузлів по зонах доступності. Натомість з’являється оновлення по одному вузлу без простою й здатність пережити падіння цілої зони.

Одиночний вузол беруть там, де обмін припустимо перервати на час робіт, — і тоді кластер лише ускладнить контур.

Часті технічні сумніви перед стартом

Перед стартом інженери замовника перевіряють не нас, а сумісність із уже працюючим контуром. Нижче — п’ять питань, які звучать найчастіше, з короткими відповідями по суті.

Наші застосунки доведеться переписувати?

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

Як зрозуміти, що кластер витримає наше навантаження?

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

У нас уже розгорнуто обмін — переїзд без простою можливий?

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

Налаштування роз’їхалися між середовищами — як це лікується?

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

Що буде, якщо нова конфігурація виявиться невдалою?

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

Обговоримо ваше завдання обміну повідомленнями

Щоб оцінка й план спиралися на факти, а не на припущення, нам потрібні вихідні дані щодо вашого контуру обміну повідомленнями.

Чим точніше ви опишете схему й профіль навантаження, тим менше припущень закладемо в кластер і політику зберігання — і тим передбачуванішими будуть терміни.

  • Схема обміну: хто публікує, хто й у яких групах читає, скільки потоків і підписок, що відбувається при сплеску.
  • Профіль навантаження: повідомлень за секунду в піку й у середньому, типовий і максимальний розмір повідомлення.
  • Вимоги до збереженості: допустима втрата при збої вузла, глибина зберігання, чи потрібен повтор доставки при відмові споживача.
  • Контур розгортання: власний сервер або хмара, скільки зон, які канали зв’язку між вузлами й як улаштований доступ.
  • Поточний стан: що вже піднято, де спостерігаєте вузькі місця, чи є журнали, метрики й описи минулих відмов.
  • Організаційні рамки: бажані терміни запуску, вікна для робіт, хто з вашого боку приймає результат.

Опишіть завдання в такому вигляді — повернемося з оцінкою та планом робіт, де будуть склад кластера, режими збереженості, порядок міграції й відкату. Формат робіт розкладемо за етапами, щоб кожен крок можна було перевірити й прийняти. Обговоримо, що закриваємо своїми силами, а що потребує змін на вашому боці.

Наші компетенції:

Останні роботи

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1542
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1393
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1081
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1368
  • Розробка логотипу компанії B2B Advance
    Розробка логотипу компанії B2B Advance
    815
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1139