За прошедшие годы я был удивлен тем, как много разработчиков программного обеспечения не понимают, насколько хорошо включение отказоустойчивости в свой код. Многие воспринимают это как преднамеренное допущение ошибок или поддержку некачественной архитектуры. Но я считаю необходимым построить систему, устойчивую к сбоям. Без них вы ложно пытаетесь построить идеальную систему, которой никогда не будет в реальной жизни.

Что такое отказоустойчивость: включение некоторой функции для автоматического противодействия эффекту ожидаемого возможного источника отказа

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

Вот типичный сценарий, который часто раздражает разработчиков:
Менеджер: Мы нашли ошибку!
Разработчик 1: Давайте найдем основную причину и исправьте это.
Разработчик 2: Основная причина заключается в том, что ресурс A зависает, когда мы иногда вызываем его в День сурка. Вероятно, отладка и исправление ресурса А займет много времени.
Менеджер: Выпустите сейчас!
Разработчик 2: Хорошо, даже если мы исправить основную причину, это может привести к сбою другими способами и иметь тот же результат. Почему бы нам не написать тайм-аут, который убивает вызов ресурса A и повторяет попытку, тогда мы будем рассмотрены в этом сценарии и сценариях сбоя сети.
Разработчик 1: Наш код и архитектура должны будь префектом!

Разработчику кажется неряшливым допустить такое вопиющее несовершенство, а затем сделать что-то, что просто заметает его под ковер. Стоит ли устранять первопричину? Да, но вы часто можете найти отказоустойчивые решения, которые охватывают множество проблем, о которых вы знаете и не знаете, и позволяют вам двигаться вперед к крайнему сроку. Кодировать в реальности означает, что вам придется смириться с некоторыми несовершенствами вашего кода и с тем, что ваши навыки кодирования и архитектуры могут вас подвести. В долгосрочной перспективе в этом сценарии да, вы должны устранить основную причину, но вы также должны оставить отказоустойчивость на случай непредвиденных ошибок. В краткосрочной перспективе отказоустойчивость дает вам некоторую передышку, чтобы расставить приоритеты.

Этот сценарий мог бы измениться и в другую сторону, если бы сбои происходили чаще. В этом случае тайм-аут все равно поможет, но может привести к такому сильному снижению производительности, что вам придется постоянно устранять основную причину. Тем не менее, он все равно прикроет вас в неожиданных ситуациях.

Другой шаблон, которому я часто следую, заключается в том, чтобы сделать то, что абсолютно необходимо для транзакции, с которой сталкивается пользователь, а затем передать все остальное фоновой задаче. Затем транзакционный код я считаю более важным и могу даже тестировать больше, чем фоновый код. Если фоновый код дает сбой, сроки исправления чего-либо значительно расширяются, и пользователь часто этого не замечает. Опять же, многие разработчики считают это плохим дизайном. Однако, когда все важно, ничто не имеет значения. Так не лучше ли отдать предпочтение самой ценной части кода? В этом случае отказоустойчивость делает транзакционный код как можно меньше, чтобы сбои не так сильно влияли на работу пользователя.

Последний пример, который я хотел бы отметить, — это архитектурный стиль, который используют многие интерфейсные фреймворки Javascript, виртуальный DOM. Виртуальный DOM позволяет вам вносить множество изменений в DOM, но затем визуализировать только то, что отличается. Это эффективно позволяет разработчикам быть очень плохими в своей работе. В идеальном мире вы бы отслеживали все изменения, необходимые для DOM, и делали бы только то, что необходимо. Это было бы более производительно, чем любой виртуальный DOM. Однако на практике трудно поддерживать такой уровень дисциплины, особенно в большой группе разработчиков. Таким образом, интерфейсные фреймворки реализовали некоторую отказоустойчивость для разработчика, который может быть плохим и писать неоптимизированный код, который в любом случае получается довольно быстро.

В следующий раз, когда вы окажетесь в ситуации, когда ответ будет «нам нужно быть лучшими разработчиками», «больше тестировать» или «нам нужно исправить основную причину», спросите себя, есть ли отказоустойчивость, которая позволит вам Будь плохим? Может быть, вы должны быть плохим только какое-то время, или, как виртуальный DOM, это то, что позволяет вам быть плохим все время. В реальном мире нам нужны рычаги, которые позволяют нам расставлять приоритеты и дают нам гибкость, чтобы действовать плохо. Вы не будете в своей игре 100% времени, поэтому найдите способы добавить слабину.