Чому NATS втрачає повідомлення під навантаженням
На стенді NATS тримає потік рівно, тому перший пік у продакшені виглядає як загадка: частина повідомлень просто не доходить. У логах відправника — тиша, у метриках — сплеск відмов, а в черзі залишаються діри, які потім відновлюють звіркою із зовнішнім джерелом.
Втрата повідомлень складається з трьох причин: розрив з’єднання в момент перемикання вузла, переповнення черги в повільного споживача й відсутність підтверджень на боці відправника.
Перемикання вузла — найчастіший сценарій розриву. Лідер іде, кластер обміну повідомленнями обирає нового, а клієнт у ці частки секунди пише в мертвий сокет і вважає дані доставленими.
Якщо повторне надсилання й підтвердження не налаштовані, ці повідомлення губляться мовчки, без помилки на клієнті. Той самий механізм дає дублі, коли повтор увімкнено, але обробник не ідемпотентний: одна подія проходить двічі й ламає стан.
Друге джерело — затримки доставки й переповнення черги. Коли споживач не встигає, потік зростає до ліміту зберігання, і далі або спрацьовує політика витіснення старих записів, або відправник отримує відмову на запис.
На піках це виглядає як рваний потік: частина подій приходить із запізненням, частина зникає, а черга відновлюється ривком і добиває обробник відкладеною пачкою.
Розбираємо, як це закривається: підтвердження й повторна доставка в потоках JetStream, ідемпотентні обробники, розміри потоків і політики зберігання під реальний профіль навантаження, перепідключення клієнтів зі збереженням буфера й перевірки стану вузлів.
Що дає відмовостійкий кластер обміну повідомленнями
Відмовостійкий кластер NATS — це не «поставили три копії й забули». Його ефекти перевіряються до бойового запуску: гасимо вузол під навантаженням, дивимося метрики й вирішуємо, чи готові до реального збою.
-
Відмова вузла не зупиняє потік. Кворум із трьох вузлів зберігає запис, коли одна машина випадає: публікація й підписка йдуть через живі вузли, клієнти перепідключаються самі. Час відновлення потоку — секунди замість простою сервісу.
-
Гарантія доставки задається явно. Повідомлення лежать на диску до підтвердження обробки, тому перезапуск сервісу-отримувача не призводить до втрати. Повторні обробки обмежені дедуплікацією й видимі в метриках, а не під час розбору інциденту.
-
Пікове навантаження не перетворюється на відмови. Якщо публікація йде швидше за обробку, різниця осідає в буфері зберігання, а не в помилках на вході — сервіс залишається доступним на сплеску.
-
Оновлення йдуть без ручних перезапусків. Вузли перезапускаються по одному, кворум зберігається, черговий не піднімає процес, що впав, руками.
-
Межі навантаження задані заздалегідь. Ліміти на отримувача й розділення потоків за призначенням не дають одному сервісу забрати ресурси в інших — деградація залишається локальною.
Кожен пункт підтверджуємо на навчаннях: гасимо вузол під навантаженням, піднімаємо трафік вище розрахункового, оновлюємо кластер на живому потоці. Результат — сервіс переживає відмову машини й пік без ручного втручання.
Режими NATS: потік, черга й постійне сховище
Режими NATS вирішують різні завдання, і вибір між ними визначається одним питанням: що має статися з повідомленням, якщо отримувач на момент відправлення недоступний. Базовий режим віддає подію всім підписникам теми відразу й ніде її не зберігає.
Черга робіт розподіляє потік між екземплярами сервісу — повідомлення йде рівно одному виконавцю. Постійне сховище JetStream записує потік на диск і дозволяє перечитати його після перезапуску.
| Варіант | Коли підходить | Обмеження |
|---|---|---|
| Потокова доставка за темою | Живі метрики, події інтерфейсу, скидання кешу | Немає зберігання: підписник недоступний — повідомлення втрачено |
| Черга робіт | Фонові завдання, розбір черги пулом виконавців | Один обробник на повідомлення; повтор при збої організовується окремо |
| Постійне сховище (JetStream) | Замовлення, платежі, аудит, обмін між сервісами | Потребує диска й налаштованої політики зберігання, вища затримка |
Вибір підказує сам характер даних: те, втрату чого можна пережити, іде за темою без зайвих накладних витрат; те, що потребує повторної обробки, — через JetStream із підтвердженням доставки.
Комбінувати режими в одній інсталяції нормально: підписка на тему й черга використовують один транспорт, тому перехід між ними — це правка налаштувань підписника, а не переписування сервісу.
Сховище вмикають точково, лише для потрібних тем, щоб не платити диском за весь трафік. Ліміт за віком або обсягом задається політикою зберігання — потік перестає зростати, а повторна обробка після збою залишається можливою.
Як ми розгортаємо кластер: етапи робіт
Кластер NATS збирається не за типовою інструкцією, а під конкретний профіль обміну: одному сервісу важлива кожна заявка, інший публікує телеметрію з допустимими втратами.
Порядок робіт у нас фіксований — він дозволяє ловити помилки топології на стенді, а не тоді, коли черга вже стала.
-
Аудит схеми обміну. Збираємо, хто публікує й хто підписується, які теми вже використовуються, де повідомлення проходить ланцюжок сервісів. Позначаємо потоки, критичні до втрати й до порядку доставки.
-
Проєктування схеми. Визначаємо склад кластера, число реплік для потоків, ліміти зберігання й політики очищення. Схема відразу лягає в конфігурацію в репозиторії, а не в документ «на згадку».
-
Налаштування кластера. Розгортаємо вузли, об’єднуємо в кластер, вмикаємо JetStream, задаємо кворум, права доступу й шифрування трафіку між вузлами. Підключаємо метрики й оповіщення щодо відставання споживачів.
-
Перевірка відмовою. Гасимо вузли по одному й парами: дивимося перевибори лідера, час відновлення, доступність публікації й підписки, відсутність дублів і втрат. На виході — заміри, а не обіцянки.
-
Передача в експлуатацію. Віддаємо конфігурації, інструкції з розгортання й відновлення, опис схеми й чергові сценарії. Ваші інженери повторюють розгортання на чистому контурі без підказки.
-
Супровід. Стежимо за здоров’ям кластера, планово оновлюємо версії, розширюємо при зростанні навантаження, розбираємо інциденти з вашою командою.
Конфігурації, схеми й регламенти на виході
Артефакти передаємо не «архівом на згадку», а робочим комплектом: будь-яку з перелічених сутностей ваша команда зможе прочитати, змінити й розгорнути без нас.
Усе лежить у вашому репозиторії, версіонується й проходить перевірку на стенді — ми проганяємо конфігурації через тестовий кластер і переконуємося, що вони відтворюються з нуля.
- Конфігурації вузлів — файли налаштувань кожного вузла з поясненнями щодо ключових параметрів: ліміти сховища, вікна зберігання повідомлень, таймаути, поведінка при втраті кворуму.
- Схема кластера — топологія маршрутів, зони відмови, точки балансування, порядок додавання й виведення вузла на обслуговування.
- Схема тем і підписок — карта потоків і черг: хто публікує, хто читає, які групи підписників ділять навантаження, де увімкнено повторне відтворення.
- Політики прав доступу — за обліковими записами й просторами: хто має право публікувати, хто лише читати, кому закритий адміністративний контур, як видаються й відкликаються ключі.
- Регламент експлуатації — планові роботи, контроль зростання сховища, ротація логів, порядок оновлення вузлів без зупинки обміну.
- Інструкції з відновлення — сценарії на випадок втрати вузла або зони: що знімається з резерву, у якій послідовності піднімається, як перевіряється цілісність.
- Моніторинг і оповіщення — набір метрик і порогів, при яких черговий отримує сигнал раніше, ніж проблема дійде до бізнес-логіки.
- Передача знань — розбір з вашими інженерами по кожному артефакту, щоб команда вела систему самостійно.
Комплект закриває повний цикл: розгорнути з нуля, змінити конфігурацію без простою, відкотити невдале оновлення й передати систему іншому підряднику без археології. Опишіть завдання — повернемося з оцінкою та планом.
Кейс: кластер NATS замість самописної черги
Компанія з білінгом і масовими розсилками тримала чергу завдань на самописному рішенні: воркери вибирали рядки з реляційної таблиці за прапором статусу, а узгодженість трималася на блокуваннях.
На піках таблиця впиралася в конкуренцію за рядки, завдання дублювалися, частина подій зникала без сліду — розбір такого інциденту займав вечір і вимагав ручної звірки з логами сервісів.
Що було до
Частка втрачених повідомлень у години пік сягала 0,3–0,5% від потоку, і в цих відсотках опинялися підтвердження оплати. Відновлення вузла після падіння займало близько 40 хвилин: воркери не перерозподіляли завдання самі, черговий піднімав їх руками.
Ручних втручань набиралося 8–12 на місяць — кожне відривало інженера від планових завдань і зсувало терміни.
Що зробили
Розгорнули кластер NATS з JetStream: потоки з дисковою персистентністю й реплікацією на кілька вузлів, споживачі з явним підтвердженням доставки й повторною видачею при помилці обробника.
Обробники зробили ідемпотентними за ключем події, щоб повтор був безпечний, а розбір «завислих» завдань замінили на автоматичну повторну видачу за таймаутом.
Що стало
На критичному потоці підтверджень оплати втрати повідомлень — нуль, включно з піковими вікнами. Вузол повертається в стрій менш ніж за хвилину: споживачі перепідключаються до живих реплік самі, ручний підйом більше не потрібен.
Втручання чергового скоротилися до планових оновлень, а завислі завдання видно в метриках потоку, а не з’ясовуються за скаргами.
Окремий ефект — передбачуваність відкату: стан черги зберігається на диску, тому перезапуск сервісу не означає втрату накопиченого потоку.
Чим кластер NATS відрізняється від одиночного брокера
Одиночний вузол NATS — один процес і одне сховище: поки він живий, публікація й підписка йдуть із мінімальною затримкою, конфігурація читається з одного файлу, а експлуатація зводиться до перезапуску служби. Точка відмови рівно одна, і вона збігається з точкою зупинки всього обміну між сервісами.
Кластер — три й більше вузлів, пов’язаних маршрутами: вони утворюють кворум, переобирають лідера й тримають копії потоків JetStream на різних вузлах. Відмова одного вузла публікацію не перериває: клієнти перепідключаються до живих, а потік відновлюється з копії.
Але якщо випадуть два вузли з трьох, запис стане до повернення третього — усвідомлена плата за узгодженість даних.
| Варіант | Коли підходить | Обмеження |
|---|---|---|
| Одиночний вузол | Розробка, тестові контури, внутрішні завдання без вимог до безперервності | Відмова вузла зупиняє обмін, оновлення потребує простою, незакомічені повідомлення губляться |
| Кластер із трьох вузлів | Продакшен, де публікація не повинна перериватися | Потрібен кворум: два вузли з трьох, що випали, блокують запис, складніша конфігурація маршрутів |
| Кластер із реплікацією потоків | Сценарії, де втрата повідомлення неприпустима: платежі, завдання, події замовлень | Затримка на підтвердження запису й у рази більший обсяг сховища |
В експлуатації різниця не менша: кластеру потрібні узгоджені конфігурації, контроль маршрутів і реплікації, рознесення вузлів по зонах доступності. Натомість з’являється оновлення по одному вузлу без простою й здатність пережити падіння цілої зони.
Одиночний вузол беруть там, де обмін припустимо перервати на час робіт, — і тоді кластер лише ускладнить контур.
Часті технічні сумніви перед стартом
Перед стартом інженери замовника перевіряють не нас, а сумісність із уже працюючим контуром. Нижче — п’ять питань, які звучать найчастіше, з короткими відповідями по суті.
Наші застосунки доведеться переписувати?
Як правило, ні: клієнтські бібліотеки є для більшості мов, змінюються адреса підключення, облікові дані й правила доступу, а логіка публікації та підписки залишається. Переписуємо лише місця, де обмін ішов в обхід черг.
Як зрозуміти, що кластер витримає наше навантаження?
Знімаємо профіль реального потоку — теми, розмір повідомлень, частку підтверджень, піки — і проганяємо на тестовому контурі. Дивимося, де зростають затримки й як поводиться сховище при відмові одного вузла.
У нас уже розгорнуто обмін — переїзд без простою можливий?
Переводимо за темами, а не цілком: певний час повідомлення йдуть в обидва контури, споживачі перемикаються за готовністю. Старий маршрут вимикаємо після звірки, тому простою в споживачів немає.
Налаштування роз’їхалися між середовищами — як це лікується?
Конфігурацію переносимо в репозиторій і описуємо декларативно: одне джерело правди для всіх середовищ, відмінності лише в параметрах оточення. Розбіжності перевіряються автоматично перед викаткою.
Що буде, якщо нова конфігурація виявиться невдалою?
Повернення займає хвилини: конфігурація версіонується, а накопичені повідомлення залишаються в сховищі й не губляться при перезапуску. Схему відкату фіксуємо й перевіряємо на тестовому контурі заздалегідь.
Обговоримо ваше завдання обміну повідомленнями
Щоб оцінка й план спиралися на факти, а не на припущення, нам потрібні вихідні дані щодо вашого контуру обміну повідомленнями.
Чим точніше ви опишете схему й профіль навантаження, тим менше припущень закладемо в кластер і політику зберігання — і тим передбачуванішими будуть терміни.
- Схема обміну: хто публікує, хто й у яких групах читає, скільки потоків і підписок, що відбувається при сплеску.
- Профіль навантаження: повідомлень за секунду в піку й у середньому, типовий і максимальний розмір повідомлення.
- Вимоги до збереженості: допустима втрата при збої вузла, глибина зберігання, чи потрібен повтор доставки при відмові споживача.
- Контур розгортання: власний сервер або хмара, скільки зон, які канали зв’язку між вузлами й як улаштований доступ.
- Поточний стан: що вже піднято, де спостерігаєте вузькі місця, чи є журнали, метрики й описи минулих відмов.
- Організаційні рамки: бажані терміни запуску, вікна для робіт, хто з вашого боку приймає результат.
Опишіть завдання в такому вигляді — повернемося з оцінкою та планом робіт, де будуть склад кластера, режими збереженості, порядок міграції й відкату. Формат робіт розкладемо за етапами, щоб кожен крок можна було перевірити й прийняти. Обговоримо, що закриваємо своїми силами, а що потребує змін на вашому боці.







