Мы на тренинге по интеграциям много разбираем обработку ошибок и мониторинг, захватываем иногда и тему поэтапного раскатывания обновлений (и автоматического отката, если что-то пошло не так), а тут на днях просто эпичная иллюстрация основных концепций.
Может быть вы слышали про падение сервисов Google 12 июня. Почти 8 часов API гугловских облачных продуктов выдавало ошибку 503 на каждый запрос.
Что произошло:
Любое обращение к API в Гугле проходит предварительный контроль: авторизацию, политики доступа, не выбрана ли квота доступа к API и т.п. Это региональный сервис, раскатанный на каждом региональном сервере. Он быстро ходит в свою базу, проверяет политики и разрешает исполнение вызова API или запрещает его. Базы с политиками синхронизированы и реплицируются почти мгновенно. Для скорости работы сервис выполнен в виде бинарника.
29 мая 2025 г. в сервис контроля была добавлена новая фича — дополнительная проверка. Обычно новые версии автоматически накатываются на внутренние проекты, и если там всё хорошо — постепенно раскатываются на все регионы. Если на какой-то стадии пошли ошибки — обновление так же автоматически откатывается. Обычно для обновлений делают "красную кнопку" — флаг, выключающий именно эту новую проверку. Ну и вообще на фичу принято вешать фича-флаги для быстрого включения/отключения.
Но вот эта новая фича по какой-то причине не имела ни красной кнопки, ни фича-флагов. А так как в базу политик не было добавлено записей о новой политике — фича не срабатывала, и обновление без ошибок раскатилось на все регионы. Вот только в нем был дефект, классический студенческий — отсутствовала проверка пустого значения!
И когда 12 июня в базу наконец добавили новую политику — случайно забыли заполнить пару полей. База политик, как мы помним, реплицируется почти мгновенно. А новый бинарник уже был раскатан во всех регионах. И он — угадайте — начал падать с null pointer exception, соответственно перекрывая доступ к вызову API.
Тут начинается какой-то процедурал-боевик, как в кино. За 2 минуты Site Reliability Engineering team отловила и оценила уровень проблемы. За 10 — выяснила причину(!). Ещё за 15 была готова "красная кнопка". Примерно через 40 минут красную кнопку раскатали, и региональные сервера начали возвращаться к работе.
Но в нагруженном регионе (us-central-1) сработал "эффект толпы": накопившиеся перезапросы стали класть поднимающийся сервис контроля политик. Потому что, вы не поверите, для этого сервиса не был настроен механизм экспоненциального откладывания ретраев, поэтому его бомбардировали все сразу. Точнее, даже экспоненциального рандомизированного откладывания. Вот тут писал про них и давал ссылку на хорошую статью. Так что всё остальное время инженеры разбирались с маршрутизацией трафика на менее нагруженные сервера.
Итого:
— Не было проверки на пустые значения;
— Не было "красной кнопки"/фича-флагов;
— Критичные управляющие данные реплицировались одномоментно, а не инкрементно по регионам;
— Код и управляющие данные накатывались в разное время, код не тестировался на разных вариантах корректных и испорченных данных;
— На критичном сервисе не был настроен механизм экспоненциального откладывания ретраев.
Я не знаю, насколько тут помог бы системный аналитик (их в Гугле вроде бы и нет), но каждый раз на тренинге я долблю и долблю: пропишите обработку всех технических ошибок и ошибок в данных! Примите решение по стратегии гарантий доставки! Если есть перепосылки-ретраи — определите механизм задержки и рассинхронизации ретраев! Это выглядит сложно и заморочено, но может уронить нагруженный сервис на несколько часов, как мы видим.
Сам же Гугл обещает, по итогам инцидента:
— сделать сервис проверки политик модульным (чтобы падение одной проверки не валило весь сервис — вот для чего нужно уходить с монолита!)
— Провести аудит всех глобально реплицируемых данных
— Принудить всех изготовителей бинарников использовать фича-флаги
— Улучшить статический анализ кода и тестирование (ну null pointer-то как пропустили?!)
Отчет об инциденте. Будьте внимательны при проектировании API!
>>Click here to continue<<