Високонавантажений бекенд на Elixir Phoenix: робота в реальному часі, відмовостійкість, кейси

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

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

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

Послуги, які ми пропонуємо
Показано 1 з 1Усі 2062 послуг
Високонавантажений бекенд на Elixir Phoenix: робота в реальному часі, відмовостійкість, кейси
Складний
від 2 тижнів до 3 місяців
Часті запитання

Розробка на Elixir: де бекенд упирається в стелю

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

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

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

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

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

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

Другий ефект — супервізори. Вузол, підсистеми й підключення описані деревом: падіння одного процесу перезапускає лише його, а не застосунок цілком.

Оновлення версії проходить без розриву з'єднань, стан сесії переживає перезапуск — втрата з'єднань більше не означає втрачену роботу користувача.

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

Стійкість під навантаженням: з'єднання, черги, повтори

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

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

Саме тут з'являється різниця в часі відновлення сервісу: секунди на підйом гілки замість хвилин на перезапуск усього застосунку.

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

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

Повторні спроби запитів робимо ідемпотентними: один ключ операції, зростаюча пауза, випадковий розкид, стеля на кількість спроб. Так зникають три класи відмов — вичерпання пулу, каскадні таймаути й «стадо» синхронних повторів, що підсилює пік. На Elixir ці механізми лежать в основі платформи, а не прикручуються поверх застосунку.

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

Варіанти реалізації: постійні процеси, гібрид, готові сервіси

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

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

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

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

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

Як відбувається розробка на Elixir: етапи інженерної роботи

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

  1. Аудит навантаження. Знімаємо профіль: частка операцій читання й запису, тривалість запитів на різних ділянках, поведінка в пікові години, ліміти зовнішніх систем. На виході — карта вузьких місць і список того, що зобов'язане переживати відмову.
  2. Схема розподілу процесів. Розбиваємо домен на ізольовані процеси під супервізорами: де тримати стан у пам'яті, де в спільному сховищі, де звертатися до бази напряму. Так падіння однієї ділянки не тягне за собою інші.
  3. Кластер і черги. Налаштовуємо розподілений кластер і фонову обробку: повторні спроби, обмеження паралелізму, захист від дублювальних задач, порядок повідомлень.
  4. Перевірка на відмовах. Навмисно виводимо з ладу вузол, зв'язок і зовнішню залежність, дивимося, чи піднімається сервіс сам, скільки запитів губиться і за який час відновлюється обслуговування.
  5. Приймання за метриками. Звіряємо результат із порогами, узгодженими до старту: частка успішних запитів, час відгуку на піку, споживання пам'яті, швидкість обробки фонової черги.
  6. Передача експлуатації. Віддаємо документацію, схеми супервізії, регламенти чергування, налаштовані метрики й оповіщення, проводимо навчання команди замовника.

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

Що передаємо на руки: схеми, регламенти й документація

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

Повноту перевіряємо практикою: розгортаємо стенд суворо за документацією і фіксуємо, де довелося здогадуватися.

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

Кейс: п'ятикратний пік без обривів і загублених заявок

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

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

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

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

Що стало на піку

Метрика До Після
Загублені заявки кілька відсотків за добу піку 0 — звернення підтверджено й зберігається
Затримка відповіді секунди, зростає з навантаженням частки секунди, від піку не залежить
Відновлення після відмови вузла десятки хвилин, вручну десятки секунд, автоматично

Аварійні розбори зникли з постійної роботи: оператори займаються заявками, а не звіркою зниклих звернень.

Що робити, якщо частина системи вже працює на іншому стеку?

Так — частину системи можна перевести на Elixir, не зупиняючи продукт, але межу ріжуть не за шарами, а за володінням даними. Спочатку фіксуємо, яка сутність кому належить: у кожної таблиці та кожного сценарію запису має бути рівно один сервіс-власник.

Інші звертаються до нього за контрактом, а не до його бази напряму. Без цієї умови змішаний стек швидко перетворюється на розбіжність даних, яку шукають тижнями.

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

На стику залишаємо тонкий шар сумісності, який знає обидва контури й уміє маршрутизувати виклики в будь-який бік.

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

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

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

Технічні сумніви: відмовостійкість, найм, підтримка

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

Як ви перевіряєте поведінку системи при відмовах?

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

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

Як шукаєте інженерів під цей стек?

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

Як влаштована підтримка після запуску?

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

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

Обговоримо задачу: розберемо профіль навантаження й ризики

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

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

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

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

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

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

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