Как ломаются сложные системы
Знаешь, что объединяет атомную электростанцию, больницу и крупный интернет-сервис? Они все работают не так, как ты думаешь.
Большую часть времени эти системы функционируют. Самолёты летают, серверы отдают страницы, врачи проводят операции. Но вот в чём фокус: любая сложная система по своей природе содержит множество скрытых неисправностей. Она работает не потому, что идеальна — а потому, что куча защитных слоёв и люди, которые постоянно латают дыры на ходу.
Мне попалась статья 1998 года — How Complex Systems Fail — написанная анестезиологом и специалистом по безопасности Ричардом Куком. Несмотря на возраст, там описаны принципы, которые каждый день подтверждаются в инцидентах на продакшене.
Давай разберёмся, почему системы не ломаются внезапно, и что с этим делать.
Катастрофа — это всегда стечение обстоятельств
Вот первое, что меня зацепило: одиночный сбой не может уничтожить сложную систему.
Представь сейф с тремя замками. Можно сломать один замок, даже два — сейф всё равно выдержит. Катастрофа случается, когда три независимых «незначительных» отказа происходят одновременно, и вместе они открывают путь к провалу.
Когда происходит авария, все спрашивают: «Кто виноват? Какая одна причина?» Но вопрос поставлен неправильно. Не существует единственного «корня зла». Есть цепочка событий, каждое из которых по отдельности было терпимым.
НАКОПЛЕНИЕ ОТКАЗОВ
───────────────────
Ожидаемая
надёжность Реальность
████████████████████████▌
████████████████▌
██████████▌
████████▌ ──▶ Время
██████▌
████▌ ◄── Отдельные мелкие
████▌ сбои накапливаются
████▌
──────████─── Слой защиты 1
──────██───── Слой защиты 2
──────█────── Слой защиты 3
────────────── Оператор/человек
Это как в анекдоте про верблюда: спина не сломалась от одной соломинки, но от сотой — сломалась. Только в инженерии соломинки — это баги в коде, недоконфигурированные серверы и выгоревшие сотрудники.
Системы всегда работают в «убитом» режиме
Сложные системы по определению неисправны.
Они продолжают функционировать благодаря избыточности и потому что люди постоянно их чинят, не останавливая. После каждого серьёзного инцидента в ретроспективном анализе обнаруживается, что систему трясло месяцами: мелкие аварии, которые «не считаются», предупреждения, которые игнорировали.
Возьми любой проект с историей. Там есть Technical Debt — накопленные костыли и быстрые решения вместо правильных. Там есть серверы, которые работают на старом железе «пока не сдохнут». Там есть сотрудники, которые держат систему на своих знаниях, недоступных в документации.
Всё это — скрытые сбои. Отдельно они не опасны. Вместе — готовый рецепт катастрофы.
Почему мы не замечаем ранние сигналы
Вот где включается психология.
Когда что-то идёт не так, мы рационализируем. «Ой, упал один сервис, ну бывает, перезапустим». «Колебание latency? Нагрузка, пройдёт». «Кто-то нажал не ту кнопку? Человеческий фактор, бывает».
Ретроспективный анализ создаёт искажение: кажется, что всё было очевидно заранее. Но до инцидента никто не видит стену. Ещё есть давление производства: показатели надо выполнять, дедлайны горят, клиенты ждут. Безопасность откладывается на потом.
ПЕТЛЯ УПУЩЕННОГО СИГНАЛА
─────────────────────────
┌────────────────────┐
│ │
▼ │
┌─────────┐ ┌─────────────┐
│ Сигнал │ НЕТ │ Может, это │
│ тревоги │◄─────── │ вообще не │
└─────────┘ │ важно? │
│ └─────────────┘
│ ДА
▼
┌─────────┐ ┌─────────────┐
│ Проверил?│ НЕТ │ Заняты, │
│ │◄─────── │ разберёмся │
└─────────┘ │ позже │
│ └─────────────┘
│ ДА
▼
КАТАСТРОФА ◄── Пора было
что-то делать!
Что делать: практические шаги
Статья не просто нытьё — она предлагает направление мышления. Вот что я вынес для себя:
- Мониторинг должен видеть деградацию, а не только падения. Если latency ползёт вверх месяц — это не норма. Если количество мелких ошибок растёт — это звоночек.
- Поощряй сообщения о «почти-инцидентах». Доклад о потенциальной проблеме — это профилактика, а не слабость.
- Регулярные стресс-тесты и хаос-инженерия. Намеренное отключение частей системы показывает, не сломается ли она целиком.
- Документируй неявные знания. Критическая информация не должна жить только в голове у одного человека.
- Принимай решения с учётом неопределённости. Говорить «я не уверен» нормально, притворяться, что всё предсказуемо, — опасно.
Моя оценка
Статья Кука написана для медицины, но на разработку она ложится почти идеально.
Особенно зацепила мысль о людях как об адаптивном элементе. Разработчики и ops-инженеры постоянно подстраивают систему: где-то костыль поставят, где-то нагрузку перераспределят, где-то в три часа ночи чинят прод, потому что «надо».
Проблема в том, что эта адаптация невидима для руководства. Менеджеры видят стабильную работу — но не видят, какой ценой она даётся.
Вывод простой: если система работает без инцидентов — это не значит, что она здорова. Это значит, что пока справляемся.
Единственное, чего в статье не хватает, — конкретных метрик и инструментов. Она задаёт рамку мышления, но не даёт чеклист.
Выводы
- Сложные системы ломаются не от одной ошибки, а от накопления мелких сбоев.
- Ранние сигналы часто игнорируются из-за привычки считать их «нормой».
- Нужны мониторинг деградации, культура сообщений о почти-инцидентах и регулярные проверки устойчивости.
- Работающая система не равна здоровой системе.
Вердикт: читать обязательно, хотя бы один раз. Потом перечитывать перед каждым серьёзным релизом.
Ссылки
- How Complex Systems Fail — оригинальная статья Ричарда Кука (1998)
- Chaos Monkey — инструмент Netflix для тестирования устойчивости к отказам
Дмитрий Полухин — продуктовый дизайнер. Пишу про разработку, AI и дизайн интерфейсов. Обо мне, контакты и профили.