Chaos Engineering для JavaScript: как ломать приложения с умом

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Ваше приложение работает идеально, пока… не ломается всё

Вы когда-нибудь замечали, что в production всё работает идеально ровно до того момента, пока не случается что-то из ряда вон? База данных зависает на секунду — и весь фронтенд превращается в белый экран. API стороннего сервиса отвечает 500-й ошибкой — и пользователи видят «Что-то пошло не так». Знакомо?

В классическом тестировании мы проверяем: «Всё работает? Ок, релизим». Но мир распределённых систем и микросервисов (а JavaScript сегодня правит и бэкендом, и фронтендом) жесток. Он требует инженерного цинизма. Именно здесь на сцену выходит Chaos Engineering — дисциплина, которая учит нас ломать систему намеренно, чтобы сделать её сильнее.

Давайте разберёмся, как применять Chaos Engineering в JS-приложениях (будь то Node.js бэкенд, React-фронтенд или Next.js сайт), и напишем код, который вы сможете запустить уже сегодня.

Что такое Chaos Engineering простыми словами?

Chaos Engineering (инжиниринг хаоса) — это практика экспериментов над распределённой системой, чтобы выявить её слабые места до того, как это сделают реальные пользователи. Netflix, например, придумал Chaos Monkey — сервис, который случайным образом убивает production-серверы в рабочее время. Звучит безумно? Да. Работает? Ещё как.

Основная идея: вместо того чтобы бояться сбоев, мы их провоцируем в контролируемой среде. Это позволяет:

  • Найти скрытые баги в логике обработки ошибок
  • Проверить, корректно ли приложение восстанавливается после падения
  • Убедиться, что мониторинг и алертинг работают
  • Повысить культуру resilience (отказоустойчивости) в команде

Для JavaScript-разработчика это особенно актуально: фронтенд-приложения зависят от сотен API, а Node.js-сервисы часто работают в облаке, где виртуальные машины могут умереть в любой момент.

Инструменты для Chaos Engineering в JavaScript

Не нужно сразу запускать Gremlin в production. Начните с малого — с локальных экспериментов. Вот что нам пригодится:

  • Gremlin — мощная платформа с SDK для Node.js. Позволяет эмулировать задержки, сбои CPU, убийство процессов.
  • Chaos Monkey от Netflix (часть Spinnaker) — для тех, кто уже живёт в микросервисной архитектуре.
  • node-chaos — легковесная библиотека для внедрения хаоса в Node.js приложения.
  • Собственные скрипты — иногда проще написать 20 строк кода, чем разворачивать тяжёлый инструмент.

Мы пойдём третьим путём и напишем свой маленький «хаос-инженер» на чистом JavaScript.

Практика: пишем Chaos Experiment для Node.js

Шаг 1. Сценарий: «Внезапная задержка API»

Представим, что у нас есть Express-сервер, который ходит в базу данных. Внезапно БД начинает отвечать с задержкой в 5 секунд. Как поведёт себя клиентский код?

Создадим middleware для Express, который с вероятностью 30% будет добавлять случайную задержку (от 1 до 10 секунд):

// chaos-middleware.js
const chaosMiddleware = (req, res, next) => {
  // Вероятность сбоя: 30%
  const shouldFail = Math.random() < 0.3;

  if (shouldFail) {
    // Случайная задержка от 1000 до 10000 мс
    const delay = Math.floor(Math.random() * 9000) + 1000;
    console.warn(`[CHAOS] Injecting latency: ${delay}ms for ${req.path}`);

    setTimeout(() => {
      // С вероятностью 10% — убиваем запрос ошибкой 500
      if (Math.random() < 0.1) {
        return res.status(500).json({ error: 'Chaos induced failure' });
      }
      next();
    }, delay);
  } else {
    next();
  }
};

module.exports = chaosMiddleware;

Подключаем middleware к приложению:

// app.js
const express = require('express');
const chaosMiddleware = require('./chaos-middleware');

const app = express();

// Включаем хаос только для эндпоинта /api/data
app.use('/api/data', chaosMiddleware);

app.get('/api/data', (req, res) => {
  // Симуляция работы с БД
  res.json({ message: 'Data from database', timestamp: Date.now() });
});

app.listen(3000, () => console.log('Server running on port 3000'));

Теперь при каждом запросе к /api/data есть шанс получить либо долгий ответ, либо 500-ю ошибку. Если ваш фронтенд написан на React — это отличный способ проверить, как работают retry-логика и fallback UI.

Шаг 2. Тестируем клиентскую часть (React)

Напишем простой компонент, который делает запрос к нашему «хаотичному» API и корректно обрабатывает ошибки и таймауты:

// DataFetcher.jsx
import { useState, useEffect } from 'react';

const DataFetcher = () => {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  const fetchData = async () => {
    setLoading(true);
    setError(null);
    try {
      // Важно: устанавливаем таймаут на запрос
      const controller = new AbortController();
      const timeoutId = setTimeout(() => controller.abort(), 8000); // 8 секунд — предел

      const response = await fetch('/api/data', { signal: controller.signal });
      clearTimeout(timeoutId);

      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }
      const result = await response.json();
      setData(result);
    } catch (err) {
      if (err.name === 'AbortError') {
        setError('Request timed out. Please try again.');
      } else {
        setError(`Failed to fetch data: ${err.message}`);
      }
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    fetchData();
  }, []);

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error}</div>;
  return <div>Data: {JSON.stringify(data)}</div>;
};

export default DataFetcher;

Запустите сервер с middleware хаоса и посмотрите, как компонент реагирует на задержки и ошибки. Если вы увидите, что UI «зависает» на 10 секунд без индикации — значит, нужно улучшать код.

Продвинутые сценарии Chaos Engineering

Задержки и 500-е ошибки — это только начало. Настоящий хаос многогранен. Вот ещё три сценария, которые стоит попробовать:

1. Убийство процесса (Node.js)

Эмулируем ситуацию, когда ваш сервис упал из-за OutOfMemory. В production

Блоги

Рекомендаций по книгам