Пошук уроків, статей та іншого контенту
З’ясуєте, як система продовжує роботу під час відмов компонентів і чим відмовостійкість відрізняється від доступності.
Відмовостійкість — це здатність системи продовжувати виконувати свої основні функції, навіть якщо окремі її компоненти вийшли з ладу.
Відмова може стосуватися:
сервера;
мережевого з’єднання;
бази даних;
зовнішнього сервісу;
диска;
окремого процесу або програмного модуля.
Наприклад, інтернет-магазин може продовжити показувати товари, якщо один із серверів тимчасово недоступний. Для цього запит користувача передають на інший сервер.
Головна ідея відмовостійкості:
Відмова одного компонента не повинна автоматично зупиняти всю систему.
Відмовостійкість не означає, що відмов у системі не буде. Вона означає, що система підготовлена до таких відмов.
Ці поняття пов’язані, але не є однаковими.
Доступність показує, яку частину часу система готова приймати й обробляти запити.
Її часто вимірюють у відсотках:
99% доступності — приблизно 3,65 дня недоступності на рік;
99,9% — приблизно 8 годин 46 хвилин;
99,99% — приблизно 52 хвилини.
Доступність відповідає на запитання:
Чи може користувач зараз скористатися системою?
Відмовостійкість описує поведінку системи під час відмови її компонентів.
Вона відповідає на запитання:
Що станеться із системою, якщо один із компонентів перестане працювати?
Система може мати високу доступність у звичайних умовах, але бути невідмовостійкою. Наприклад, один сервер працює майже без перерв, але його поломка зупиняє весь сервіс.
І навпаки, відмовостійка система може тимчасово працювати в обмеженому режимі. Наприклад, користувачі можуть переглядати товари, але не можуть оформити замовлення. Основна частина системи доступна, хоча деякі функції недоступні.
Доступність — скільки часу система працює.
Відмовостійкість — як система переживає відмови.
Відмовостійкість допомагає підтримувати високу доступність, але не гарантує її автоматично.
Надлишковість означає наявність додаткових компонентів, які можуть замінити основний.
Приклади:
два або більше серверів замість одного;
резервна база даних;
кілька мережевих з’єднань;
дубльовані блоки живлення.
Якщо всі запити обробляє лише один компонент, його відмова може зупинити систему. Якщо є резервний компонент, система може продовжити роботу.
Важливо, щоб резервний компонент справді був готовий до роботи. Просто встановити другий сервер недостатньо: він має мати потрібну конфігурацію, дані та доступ до залежностей.
Коли основний компонент відмовляє, система повинна визначити це та переключити запити на резервний.
Типовий сценарій:
Система надсилає запити до основного сервера.
Спеціальний механізм перевіряє, чи відповідає сервер.
Основний сервер перестає відповідати.
Нові запити передаються на резервний сервер.
Після відновлення основний сервер можна повернути до роботи.
Перемикання може бути:
автоматичним — без участі оператора;
ручним — оператор сам запускає резервний компонент.
Автоматичне перемикання зазвичай швидше, але його потрібно правильно налаштувати. Помилкове рішення системи може спричинити зайві перемикання або втрату даних.
Система не може відреагувати на відмову, якщо не вміє її виявляти.
Для цього використовують перевірки стану:
чи відповідає сервер;
чи може сервіс виконати просту операцію;
чи доступна база даних;
чи не перевищено час очікування.
Важливо відрізняти:
сервіс працює, але відповідає повільно;
сервіс не працює зовсім;
сервіс відповідає, але повертає помилки.
Надто короткий час очікування може створити хибне враження відмови. Надто довгий — затримати перемикання на резерв.
Іноді неможливо зберегти всі функції системи. Тоді система може перейти в обмежений режим.
Наприклад:
показувати кешовані дані замість свіжих;
дозволяти читання, але тимчасово забороняти зміни;
приховувати другорядну функцію;
приймати запит і обробляти його пізніше.
Це називають плавним погіршенням функціональності. Краще надати користувачу частково працюючий сервіс, ніж повністю зупинити всю систему.
Нижче наведено спрощений приклад на JavaScript. Функція спочатку звертається до основного сервісу. Якщо він не відповідає або повертає помилку, використовується резервний сервіс.
function createService(name, shouldFail = false) {
return async function getData() {
// Імітуємо затримку відповіді сервісу
await new Promise((resolve) => setTimeout(resolve, 100));
if (shouldFail) {
throw new Error(`${name} недоступний`);
}
return {
source: name,
items: ["Товар 1", "Товар 2"]
};
};
}
async function getItems(primaryService, backupService) {
try {
// Спочатку використовуємо основний сервіс
return await primaryService();
} catch (error) {
console.log(`Основний сервіс не відповів: ${error.message}`);
try {
// У разі відмови перемикаємося на резервний сервіс
return await backupService();
} catch (backupError) {
// Якщо відмовили обидва сервіси, повідомляємо про помилку
throw new Error("Дані тимчасово недоступні");
}
}
}
const primaryService = createService("Основний сервіс", true);
const backupService = createService("Резервний сервіс");
getItems(primaryService, backupService)
.then((result) => {
console.log("Отримані дані:", result);
})
.catch((error) => {
console.error(error.message);
});У цьому прикладі:
основний сервіс навмисно повертає помилку;
система перехоплює цю помилку;
запит повторюється до резервного сервісу;
користувач отримує дані, якщо резервний сервіс працює.
Це спрощена модель. У реальній системі також потрібно перевіряти стан резервного сервісу, контролювати час очікування та стежити за узгодженістю даних.
У розподіленій системі компоненти можуть відмовляти не одночасно.
Наприклад:
вебсервер працює;
база даних працює;
сервіс оплати недоступний.
Це називають частковою відмовою. Вона складніша за повну відмову системи, тому що частина операцій продовжує працювати, а частина — ні.
Відмовостійка система має чітко визначити:
які функції залежать від компонента;
які функції можна тимчасово вимкнути;
чи можна використати резерв;
яке повідомлення показати користувачу.
Наприклад, якщо недоступний сервіс рекомендацій, магазин може продовжити оформлення замовлень. Рекомендації є другорядною функцією, тому їхню помилку не потрібно поширювати на всю систему.
Відмова компонента особливо небезпечна, якщо вона спричиняє втрату або пошкодження даних.
Під час проєктування потрібно враховувати:
де зберігаються дані;
чи є резервна копія;
як відновити дані після відмови;
чи не буде одна операція виконана двічі;
чи узгоджені дані між основним і резервним компонентами.
Наприклад, якщо платіж успішно виконано, але відповідь не дійшла до магазину, повторення запиту може призвести до подвійного списання коштів. Тому для важливих операцій система повинна розрізняти повторний запит і нову операцію.
Відмовостійкість — це не лише «запустити другий сервер». Потрібно продумати поведінку системи та її даних у момент відмови.
Відмовостійкість не усуває всі проблеми.
Система може залишатися недоступною, якщо:
одночасно відмовили всі резервні компоненти;
несправність поширилася на спільну залежність;
неправильно налаштовано перемикання;
резервні дані застаріли;
відмова сталася через помилку в програмному коді;
відмовив компонент, спільний для всіх копій.
Наприклад, два сервери не допоможуть, якщо вони використовують один несправний маршрутизатор або одну недоступну базу даних.
Тому під час проєктування потрібно шукати не лише окремі компоненти, а й єдині точки відмови — компоненти, відмова яких зупиняє всю систему.
Резервний сервер може бути:
неправильно налаштований;
без актуальних даних;
недоступний для мережі;
несумісний з іншими компонентами.
Резерв потрібно регулярно перевіряти.
Автоматичні повтори можуть допомогти під час короткочасної помилки. Але необмежені повтори:
збільшують навантаження;
затримують відповідь;
можуть повторно виконати небезпечну операцію.
Кількість повторів і час очікування мають бути обмежені.
Якщо не працює другорядна функція, це не обов’язково означає, що потрібно зупинити весь сервіс. Варто ізолювати помилку та продовжити роботу незалежних функцій.
Система може добре працювати в нормальних умовах, але помилково поводитися під час перемикання. Потрібно перевіряти сценарії:
відмови основного сервера;
недоступності бази даних;
повільної відповіді;
відновлення компонента;
одночасної відмови кількох компонентів.
Високий показник доступності не доводить, що система правильно переживе відмову. Потрібно окремо перевіряти поведінку системи в аварійних ситуаціях.
Відмовостійкість — це здатність системи продовжувати роботу після відмови окремих компонентів.
Доступність показує, скільки часу система доступна користувачам.
Для відмовостійкості використовують надлишковість, резервні компоненти та перемикання.
Система повинна вміти виявляти відмови.
Якщо всі функції зберегти неможливо, система може перейти в обмежений режим.
Часткову відмову потрібно ізолювати, щоб вона не зупинила незалежні функції.
Резервні компоненти та дані потрібно регулярно перевіряти.
Відмовостійкість не гарантує безперервну роботу за будь-яких умов, але зменшує вплив окремих відмов.