Пошук уроків, статей та іншого контенту
Визначите необхідні ресурси системи на основі навантаження, зростання аудиторії, пікових значень і запасу потужності.
Capacity planning — це визначення ресурсів, необхідних системі для оброблення поточного та майбутнього навантаження.
Під ресурсами можуть матися на увазі:
CPU;
оперативна пам’ять;
кількість екземплярів сервісу;
пропускна здатність мережі;
з’єднання з базою даних;
дисковий простір;
продуктивність кешу;
пропускна здатність черг повідомлень.
Мета capacity planning — не просто знайти мінімальну конфігурацію, яка працює сьогодні. Потрібно врахувати:
поточне навантаження;
зростання аудиторії;
пікові значення;
запас потужності;
вимоги до доступності та відмовостійкості.
Недостатня оцінка призводить до повільної роботи та збоїв. Надмірна — до зайвих витрат.
Перед розрахунками потрібно визначити, що саме навантажує систему.
Варто розрізняти кілька показників:
зареєстровані користувачі — усі акаунти;
активні користувачі — користувачі, які взаємодіють із системою протягом певного періоду;
одночасні користувачі — користувачі, які виконують дії в один момент;
користувачі в піковий період — навантаження під час найбільш активного часу.
Наприклад, 1 мільйон зареєстрованих користувачів не означає, що система одночасно обслуговує 1 мільйон запитів.
Один із головних показників — RPS або requests per second.
Якщо за годину система обробляє 360 000 запитів, середнє навантаження становить:
[ RPS_{avg} = \frac{360000}{3600} = 100 ]
Але середнє значення не можна використовувати безпосередньо для вибору потужності. Реальне навантаження зазвичай нерівномірне.
Якщо піковий коефіцієнт дорівнює 5, то:
[ RPS_{peak} = 100 \times 5 = 500 ]
Для баз даних і кешів важливо знати співвідношення операцій читання та запису.
Наприклад:
90% — читання;
10% — запис.
Це впливає на вибір архітектури:
читання часто можна масштабувати кешуванням і репліками;
записи зазвичай створюють більше обмежень для бази даних;
різні типи операцій можуть мати різну вартість.
Два запити з однаковим RPS можуть створювати зовсім різне навантаження.
Простий запит за індексом може бути дешевим, а запит із:
кількома JOIN;
сортуванням великого набору;
агрегаціями;
зверненням до зовнішніх сервісів
може потребувати значно більше CPU, пам’яті та часу.
Тому capacity planning потрібно виконувати не лише за кількістю запитів, а й за їхніми профілями.
Розділіть навантаження на типові операції:
перегляд сторінки;
пошук;
створення замовлення;
завантаження файлу;
надсилання повідомлення;
фонове опрацювання задачі.
Для кожного сценарію визначте:
частку від загального навантаження;
середню тривалість;
пікову частоту;
залежності від бази даних, кешу або зовнішніх сервісів.
Середній RPS можна обчислити так:
[ RPS_{avg} = \frac{N}{T} ]
де:
(N) — кількість запитів;
(T) — тривалість періоду в секундах.
Пікове навантаження:
[ RPS_{peak} = RPS_{avg} \times P ]
де (P) — коефіцієнт піку.
Коефіцієнт потрібно отримувати з реальних метрик, якщо вони доступні. Для нової системи його можна оцінити на основі очікуваної поведінки користувачів, але таке значення буде припущенням.
Якщо навантаження зростає на (g) відсотків щомісяця, через (m) місяців воно становитиме:
[ Load_{future} = Load_{current} \times (1 + g)^m ]
Наприклад, при навантаженні 500 RPS, зростанні 10% щомісяця та горизонті 6 місяців:
[ 500 \times 1.1^6 \approx 886 ]
Потрібно відрізняти:
лінійне зростання — навантаження додається приблизно однаковими порціями;
експоненційне зростання — навантаження збільшується у відсотках;
сезонне зростання — навантаження змінюється залежно від дня, місяця або події.
Для більшості продуктів прогноз є приблизним. Його слід регулярно переглядати за фактичними метриками.
Система не повинна працювати постійно на межі можливостей.
Якщо розраховане майбутнє пікове навантаження дорівнює 886 RPS, а запас становить 30%, цільова потужність:
[ Capacity_{target} = 886 \times 1.3 \approx 1152 ]
Запас потрібен для:
неточності прогнозу;
короткочасних сплесків;
нерівномірного розподілу трафіку;
збільшення складності запитів;
аварійного вимкнення частини інфраструктури;
виконання фонових задач.
Запас не замінює автоматичне масштабування. Він лише дає системі час відреагувати на непередбачене зростання.
Припустімо, тестування показало, що один екземпляр сервісу стабільно обробляє 120 RPS за прийнятної затримки.
Цільове навантаження — 1152 RPS.
Мінімальна кількість екземплярів:
[ Instances_{min} = \left\lceil \frac{1152}{120} \right\rceil = 10 ]
Округлення вгору обов’язкове, оскільки частину екземпляра запустити неможливо.
Але 10 екземплярів — це лише розрахунок пропускної здатності. Потрібно також врахувати відмовостійкість.
Якщо один екземпляр може вийти з ладу, кількість потрібно визначити так, щоб після його втрати система все ще витримувала цільове навантаження:
[ Instances_{HA} = \left\lceil \frac{1152}{120} \right\rceil + 1 = 11 ]
У реальній системі екземпляри також розподіляють між зонами доступності або іншими доменами відмови.
Не варто планувати роботу CPU на 100%. При такому підході короткий сплеск може одразу призвести до деградації.
Наприклад, якщо сервіс має 4 CPU на екземпляр, але прийнятний рівень завантаження — 70%, ефективна доступна потужність становить:
[ 4 \times 0.7 = 2.8 ]
Планувати потрібно за фактичною продуктивністю під навантаженням, а не лише за кількістю CPU.
Водночас CPU — не єдиний показник. Сервіс може бути обмежений:
кількістю з’єднань до бази даних;
пам’яттю;
диском;
мережевою пропускною здатністю;
зовнішнім API.
Для приблизної оцінки кількості одночасних операцій можна використати закон Літтла:
[ Concurrency = Throughput \times Latency ]
Якщо система обробляє 500 запитів за секунду, а середня тривалість запиту — 200 мс:
[ Concurrency = 500 \times 0.2 = 100 ]
Отже, у середньому одночасно обробляється близько 100 запитів.
Цей розрахунок допомагає оцінити:
кількість робочих потоків;
розмір пулу з’єднань;
кількість одночасних задач;
вимоги до пам’яті.
Важливо використовувати одиниці вимірювання:
RPS — запити за секунду;
latency — секунди;
результат — кількість одночасних операцій.
Середня затримка не завжди достатня. Для capacity planning корисніше аналізувати також p95 або p99 latency, адже саме вони показують поведінку повільних запитів.
База даних часто стає головним обмеженням системи.
Потрібно оцінити:
кількість операцій читання за секунду;
кількість операцій запису за секунду;
розмір і складність запитів;
кількість одночасних з’єднань;
обсяг даних;
темп зростання даних;
розмір індексів;
час резервного копіювання;
запас дискового простору.
Якщо система створює 2 ГБ даних на день, то за рік потрібно:
[ Storage_{year} = 2 \times 365 = 730 \text{ ГБ} ]
Але фактична потреба буде більшою через:
індекси;
журнали;
службові дані;
резервні копії;
тимчасові файли;
репліки.
Якщо коефіцієнт додаткового простору дорівнює 1,5:
[ 730 \times 1.5 = 1095 \text{ ГБ} ]
Резервні копії та репліки потрібно планувати окремо, якщо вони зберігаються в тій самій інфраструктурі.
Кожен екземпляр застосунку може відкривати певну кількість з’єднань до бази даних.
Наприклад:
12 екземплярів сервісу;
20 з’єднань на екземпляр.
Загальна кількість з’єднань:
[ 12 \times 20 = 240 ]
Якщо база підтримує лише 200 з’єднань, така конфігурація буде некоректною навіть тоді, коли CPU та пам’яті достатньо.
Розмір пулу не потрібно збільшувати автоматично. Надто великий пул може погіршити ситуацію: база витрачатиме ресурси на перемикання між великою кількістю одночасних операцій.
Мережеве навантаження можна приблизно оцінити за кількістю запитів і їхнім розміром:
[ Bandwidth = RPS \times AverageResponseSize ]
Якщо система обробляє 800 RPS, а середній розмір відповіді становить 100 КБ:
[ 800 \times 100 \text{ КБ} = 80000 \text{ КБ/с} ]
Це приблизно 78,1 МіБ/с або близько 625 Мбіт/с без урахування додаткових витрат протоколів.
Потрібно врахувати:
вхідний і вихідний трафік;
розмір заголовків;
повторні запити;
передавання файлів;
трафік між сервісами;
реплікацію та резервне копіювання.
Середній розмір відповіді може суттєво відрізнятися від пікового, тому для критичних сценаріїв варто використовувати реальні вимірювання.
Нехай система має такі характеристики:
поточне середнє навантаження — 180 RPS;
піковий коефіцієнт — 4;
очікуване зростання за 6 місяців — 50%;
запас потужності — 30%;
один екземпляр обробляє 100 RPS;
один екземпляр має 15 з’єднань до бази даних;
один запит створює в середньому 80 КБ відповіді.
Спочатку обчислимо поточний пік:
[ 180 \times 4 = 720 \text{ RPS} ]
Після очікуваного зростання:
[ 720 \times 1.5 = 1080 \text{ RPS} ]
З урахуванням запасу:
[ 1080 \times 1.3 = 1404 \text{ RPS} ]
Кількість екземплярів:
[ \left\lceil \frac{1404}{100} \right\rceil = 15 ]
Якщо потрібно витримати відмову одного екземпляра:
[ 15 + 1 = 16 ]
Загальна кількість з’єднань до бази:
[ 16 \times 15 = 240 ]
Пропускна здатність для відповідей:
[ 1404 \times 80 \text{ КБ} = 112320 \text{ КБ/с} ]
Це приблизно 109,7 МіБ/с або 878 Мбіт/с без урахування службових витрат.
Окремо потрібно перевірити, чи витримає база 240 з’єднань і відповідний рівень операцій. Якщо ні, збільшення кількості екземплярів застосунку не вирішить проблему — воно може лише збільшити тиск на базу.
Нижче наведено runnable-приклад для базового розрахунку пікового навантаження, майбутньої потужності та кількості екземплярів.
function calculateCapacity({
averageRps,
peakFactor,
growthRate,
months,
headroom,
instanceCapacity,
instancesToTolerateFailure = 0,
}) {
if (
averageRps <= 0 ||
peakFactor <= 0 ||
growthRate < 0 ||
months < 0 ||
headroom < 0 ||
instanceCapacity <= 0 ||
instancesToTolerateFailure < 0
) {
throw new Error("Параметри мають містити коректні невід'ємні значення");
}
const currentPeakRps = averageRps * peakFactor;
const futurePeakRps = currentPeakRps * (1 + growthRate) ** months;
const targetCapacityRps = futurePeakRps * (1 + headroom);
const requiredInstances = Math.ceil(targetCapacityRps / instanceCapacity);
const plannedInstances =
requiredInstances + instancesToTolerateFailure;
return {
currentPeakRps,
futurePeakRps,
targetCapacityRps,
requiredInstances,
plannedInstances,
};
}
const result = calculateCapacity({
averageRps: 180,
peakFactor: 4,
growthRate: 0.08,
months: 6,
headroom: 0.3,
instanceCapacity: 100,
instancesToTolerateFailure: 1,
});
console.log(`Поточний пік: ${result.currentPeakRps.toFixed(0)} RPS`);
console.log(`Пік через 6 місяців: ${result.futurePeakRps.toFixed(0)} RPS`);
console.log(`Цільова потужність: ${result.targetCapacityRps.toFixed(0)} RPS`);
console.log(`Мінімум екземплярів: ${result.requiredInstances}`);
console.log(`Заплановано екземплярів: ${result.plannedInstances}`);У прикладі:
peakFactor — коефіцієнт піку;
growthRate — щомісячне зростання у вигляді десяткового дробу;
headroom — запас потужності;
instanceCapacity — пропускна здатність одного екземпляра;
instancesToTolerateFailure — кількість екземплярів, які можна втратити без перевищення розрахованої потужності.
Результат цього розрахунку — початкова оцінка. Реальну instanceCapacity потрібно отримати за допомогою тестування.
Capacity planning без вимірювань містить багато припущень. Навантажувальне тестування допомагає визначити реальну межу системи.
Під час тестування варто перевірити:
максимальний стабільний RPS;
p95 і p99 latency;
рівень помилок;
використання CPU;
використання пам’яті;
кількість з’єднань до бази;
час відповіді бази;
мережевий трафік;
поведінку кешу;
довжину черг.
Тест потрібно проводити на навантаженні, максимально наближеному до реального:
із подібним співвідношенням читання та запису;
із реалістичним розміром даних;
із типовими сценаріями користувачів;
із такими самими залежностями, як у production.
Тестування лише одного простого endpoint не показує повну пропускну здатність системи.
Короткий тест може не виявити проблеми, які виникають через тривалу роботу:
витік пам’яті;
поступове заповнення диска;
накопичення повідомлень у черзі;
деградацію кешу;
блокування в базі;
збільшення часу фонових задач.
Тому окрім короткого тесту пікового навантаження корисно виконувати тривалий тест зі стабільним навантаженням.
Розрахунок потрібно пов’язати з моніторингом. Корисні метрики:
RPS за endpoint;
кількість одночасних запитів;
p50, p95, p99 latency;
частка помилок;
CPU та пам’ять;
кількість відкритих з’єднань;
використання диска;
мережевий трафік;
hit rate кешу;
довжина черг;
час очікування задачі;
затримка та помилки зовнішніх сервісів.
Особливо важливо контролювати не лише середнє значення, а й пікові періоди.
Наприклад, середній CPU за день може становити 35%, але під час коротких піків досягати 95%. Середнє значення приховає цю проблему.
Єдиного правильного відсотка запасу не існує. Він залежить від:
точності прогнозу;
вартості додаткових ресурсів;
часу запуску нових ресурсів;
важливості системи;
швидкості масштабування;
сезонності навантаження;
вимог до доступності.
Менший запас можливий, якщо:
масштабування автоматизоване;
запуск нових екземплярів займає секунди;
навантаження добре прогнозується;
система може тимчасово обмежувати функціональність.
Більший запас потрібен, якщо:
масштабування повільне;
є великі непередбачувані сплески;
система критична для бізнесу;
частина ресурсів може вийти з ладу;
зовнішні залежності мають нестабільну продуктивність.
Запас потрібно рахувати для кожного критичного ресурсу окремо. 30% вільного CPU не допоможуть, якщо вже вичерпано з’єднання до бази даних.
Середній RPS приховує піки. У результаті система може працювати більшість часу, але падати під час найбільш важливих періодів.
Потрібно аналізувати погодинні, хвилинні та секундні піки.
Кількість користувачів не визначає навантаження без інформації про їхню активність.
Два продукти з однаковою аудиторією можуть мати різний RPS через різну частоту дій і складність запитів.
Значення на кшталт «один сервер витримує 1000 запитів за секунду» не має сенсу без уточнення:
які це запити;
який розмір відповіді;
яка затримка;
який рівень помилок;
яка база даних;
які обмеження пам’яті та CPU.
Продуктивність потрібно підтверджувати навантажувальним тестом.
Сервіс може мати достатньо CPU, але чекати на:
базу даних;
кеш;
платіжну систему;
сервіс автентифікації;
чергу повідомлень.
Потрібно оцінювати пропускну здатність усього ланцюжка, а не одного компонента.
Конфігурація, яка витримує навантаження лише за умови роботи всіх екземплярів, не є стійкою до відмов.
Потрібно заздалегідь визначити, скільки ресурсів може бути втрачено без порушення цільових показників.
Великий запас також може бути проблемою:
зростають витрати;
складніше підтримувати інфраструктуру;
невикористані ресурси маскують неефективність;
помилки в архітектурі залишаються непоміченими.
Запас має бути обґрунтованим і переглядатися після отримання нових даних.
Навіть якщо RPS не змінюється, база може сповільнитися через зростання таблиць, індексів і резервних копій.
Плануйте не лише обчислювальні ресурси, а й довгострокову ємність сховища.
Для початкової оцінки використовуйте такий порядок:
Опишіть основні сценарії користувачів.
Визначте середній і піковий RPS.
Оцініть зростання на потрібний період.
Додайте запас потужності.
Виміряйте продуктивність одного екземпляра тестуванням.
Обчисліть кількість екземплярів.
Перевірте базу даних, кеш, черги та мережу.
Додайте ресурси для відмовостійкості.
Перевірте конфігурацію навантажувальним тестом.
Налаштуйте моніторинг і регулярно переглядайте прогноз.
Capacity planning визначає ресурси для поточного та майбутнього навантаження.
Для розрахунків потрібно враховувати середній RPS, піки, зростання та запас потужності.
Кількість користувачів сама по собі не показує реальне навантаження.
Кількість екземплярів визначають на основі виміряної пропускної здатності одного екземпляра.
Закон Літтла допомагає оцінити кількість одночасних операцій через throughput і latency.
Базу даних потрібно перевіряти за операціями, з’єднаннями, диском та зростанням даних.
Запас потужності потрібен для сплесків, похибок прогнозу та відмов.
Теоретичні оцінки потрібно підтверджувати навантажувальним тестуванням.
Capacity planning — це постійний процес, який оновлюється за production-метриками.