Какие проблемы появляются при переходе из монолитной архитектуры к микросервисной? Как с ними справляться в пиковые нагрузки? Ответим на эти вопросы на примере Сбербанк Онлайн.
Меня зовут Артём Арюткин, я руковожу проектным офисом в Сбере. Весь мой профессиональный опыт завязан на то, чтобы сделать Сбербанк Онлайн надёжнее. Расскажу про основные принципы отказоустойчивой архитектуры и весь путь эволюции Сбербанк Онлайн.
Что такое Сбербанк Онлайн
Сбербанк Онлайн в числах:
80 миллионов MAU. Если вдруг сервис не доступен для 1% клиентов, 800 тысяч клиентов страдают в моменте.
200+ команд — если вы верите, что можете управлять 200 командами, напишите мне, мы вас давно ищем.
500+ микросервисов — как со звездами, каждую минуту где рождается новый микросервис, умирает старый и на его месте возрождается новый и улучшенный.
120 тысяч входов в минуту.
~ 15% рост нагрузки ежегодно. То, что было сделано в прошлом году, уже не поможет в следующем и придётся придумывать что-то новое.
99,99 — наш уровень доступности.
Это лучше объяснить на примере. Представьте, что вы стоите в огромной очереди в супермаркете с полной тележкой. Наконец-то дошли до кассы, но за вами снова собралась очередь. Вы судорожно перекладываете товары на ленту, а потом в пакет. Кассир называет вам сумму, но у вас на карте не хватает 1000 рублей. Вы заходите в Сбербанк Онлайн, а сервис перевода на карту недоступен. Физически деньги есть на вкладе, но перевести их на карту у вас не получается. И тут начинается: «Галя, у нас отмена». Вас ненавидит вся очередь, а ваши эмоции лучше даже не представлять.
На самом деле, тут кроется ключевое отличие от развлекательных сервисов.
Представьте, что вы сидите вместе с другом на диване и хотите показать ему мем в одной из социальных сетей. И вот сервис загрузки не работает. Обидно, точно. Но, поверьте, ваши эмоции будут очень разными.
Место в ландшафте банка
Обычно клиент использует 4 канала:
АТМ (банкоматы);
мобильное приложение;
веб;
приложение для обслуживания клиента в офисе.
Классический слой интеграции в банках — это ESB (Enterprise Service Bus). Мы постепенно переходим на интеграцию посредствам rest’ов.
Дальше идут различные «фабрики»: карты, кредиты, вклады, платежи, инвестиционные продукты и прочее. Важно понимать, что Сбербанк Онлайн не принимает решение о том, выдавать ли вам кредит или какая будет у вас ставка по вкладу, не проводит платежи за сотового оператора. Сбербанк Онлайн — это интерфейс для доступа к сервису платежа, за «фабрикой платежей» стоят платёжные шлюзы, за платёжными шлюзами — система оператора, а за системой оператора — ещё платёжные шлюзы.
Архитектура СБОЛ
Серверная часть СБОЛ устроена так:
Есть шарды, которые полностью изолированы и самостоятельны. Для лучшей визуализации представьте, что каждая шарда — это подводная лодка. В каждой из них живёт конкретный клиент. Например, я живу в шарде 7, а кто-то из вас — в шарде 1. Это, условно, никогда не меняется для 99% клиентов, хотя, конечно, есть разные случаи и сценарии. Распределение по шардам происходит не совсем случайно, в этом есть определённая логика, но будем считать, что случайно.
Шарда представляет собой сервер приложения БД для хранения операций до 12 месяцев. Данные постарше хранятся уже в архивной БД, отдельным слоем. Но на самом деле это не совсем так. Они реплицируются онлайн GoldenGate и хранят актуальные данные с отставанием в 10 минут.
Также есть резервные шарды, они нужны на случай, если вдруг одна из основных упадёт. В таком случае клиенты перебрасываются в резервную шарду. Там нет данных в моменте, но они подтягиваются из архивной базы, как только клиент заходит в СБОЛ. При этом ни о каких проблемах и инцидентах клиент не узнаёт. Интерфейс для него никак не меняется.
Тот же самый подход используется при обновлениях. Мы накатываем новую версию на шарду, а клиентов в это время перенаправляем в резервную и обновляем основную без всяких проблем.
При этом относительно недавно мы трансформировали наш огромный legacy-монолит в безумные 500+ микросервисов. В итоге получилось, что в одной шарде существует legacy-монолит и микросервисная платформа, которая включает в себя базовые библиотеки и приложения для обработки клиентских запросов:
сервис аудита — обязательная штука, в банке без этого нельзя;
сервис журналирования;
сервис мониторинга;
история операций;
и прочее.
Их там больше 40 штук.
Также все каналы у нас изолированы. Если упадёт один канал, например, АТМ, то все остальные останутся живы в рамках этой шарды.
Организационная структура
СБОЛ — это очень сложноуправляемая история, которая работает в матричной структуре управления. Это такой способ организации, когда приходится работать с теми, с кем дают. Нельзя человека «бить», наказывать, лишать премии или повышения — ничего с ним сделать нельзя, какой бы он нехороший ни был. Можно ходить к его начальнику и говорить, что он не работает, но это тоже может не помочь. Всегда существует вероятность, что он осознанно не хочет заниматься нашей задачей. В общем, все это особенности «матричной» структуры управления.
Почему мы об этом говорим? Команда, отвечающая за надёжность «на круг», находится в левой части (Платформа СБербанк Онлайн). При этом работать над надёжностью без привлечения продуктовых команд («Платежи и переводы», «Кошелек клиента» и прочие) не получится.
И вот тут мы сталкиваемся со стандартными для матричной структуры проблемами: приоритезацией задач, разработкой процедур согласования и включения в бэклоги и т. п. При этом, всегда есть разногласия по реализации. К примеру, команда платформы может быть не готова реализовывать обратную совместимость, что делает задачу для продуктовых команд более трудоёмкой. Тут же сразу возникает конфликт ресурсов и прочее.
А есть ли преимущества? Конечно! Именно это помогает платформе развиваться, искать пути решения задачи без привлечения продуктовых команд и создавать более удобные инструменты для них.
Что такое High Season
High Season — период пиковой нагрузки. Это различные праздники, такие как Новый год, 8 марта, 23 февраля и «майские». А ещё подготовка к школе и другие периоды, когда клиенты чаще заходят в Сбербанк Онлайн и совершают транзакции.
Несмотря на то, что это всего лишь пара дней, во время них необходимо как угодно продержаться, «доползти на пузе», но дать клиентам базовый сервис. У них может быть недоступна какая‑то красивость, например, не подгрузится аватар — главное, чтобы были доступны core-сервисы. Если мы упадём, будет беда! Клиенты не получат доступ к своим средствам в реально важный для них момент времени, как в том случае с супермаркетом.
Подготовка к пиковым нагрузкам
Сложно описать как мы готовимся к пиковым нагрузкам. На самом деле в системах класса Highload движущим фактором являются не бизнес-требования, а требование надежности. Поэтому подготовку к High Season можно условно свести к следующим пунктам:
Чтобы справиться с пиковыми нагрузками, необходимо придерживаться следующих эвристик:
→ Анализ нагрузки и поведения АС в прошлом периоде
Мы стандартно анализируем нагрузку: смотрим, что было за прошлый период, какие инциденты, как мы пережили пиковые моменты.
→ Прогноз нагрузки
Дальше строим прогноз нагрузки. Когда я рассказывал про Сбербанк Онлайн в числах, то говорил про 120 тысяч входов в минуту. Для нас это обычный день, потому что в пике бывает и 200 тысяч входов в минуту.
Надо всегда анализировать, обсуждать вместе с бизнесом их ожидания по пиковым нагрузкам, не забывать про маркетинговые активности. Самый лучший вариант — разработка процесса, который позволит систематизировать изменения по нагрузке и функциональности.
→ Определение максимума нагрузки для прогноза
Мы используем нагрузочное тестирование, всякие подходы вроде Chaos Engineering и прочее. То есть пытаемся максимально «сломать» систему и посмотреть, что будет. Здесь выявляются разные классные штуки, например, единая точка отказа. Допустим, аудит для банков — обязательный сервис. У нас он был реализован отдельным микросервисом. Был нюанс, что мы вовремя не учли зависимость всех сервисов от него и в случае его недоступности всё «ломалось». И получается, что Сбербанк Онлайн падает вместе с одним‑единственным отказавшим сервисом, хотя, казалось бы, он не критичен для самого клиента и не несёт никакого полезного смысла. Клиенты могут работать, у них всё будет хорошо, но есть такой нюанс.
→ Оптимизация конфигурации
Это широкий спектр задач. Мы можем добавить шарду, поменять СХД или «железки», подкрутить что‑то в параметрах. Например, после миграции с монолита на микросервисы из‑за особенностей реализации асинхронных сервисов в микросервисах и из‑за того, что серверов много, у нас переполнялись TCP‑подключения к MQ. Это привело к проблемам: мы «убивали» MQ.
Естественно, нужно было эту задачу решать оптимизацией конфигурации. Потому что в наших условиях изменения и доработки заняли бы порядка года, а мы подошли к High Season.
→ Доработки: кеширование и прочее.
Самый тяжёлый и неприятный вариант — выполнить доработки. Например, к вам приходит ваш бэк, который отвечает за вклады, и говорит, что не может развиваться и тянуть нагрузку. Поэтому приходится кешировать и показывать информацию клиенту с небольшим отставанием. Клиент всё равно не всегда обновляет вклады, к примеру.
С чего начать?
Напоминаю, что я руководитель проектного офиса, поэтому у меня есть секретный управленческий приём: взять и сделать!
Представим, что на схеме архитектуры СБОЛ ничего нет, в том числе, архивных баз, а есть только шарда 1. Так как к нам обращалось всё больше клиентов, количество данных тоже росло. Поэтому мы упёрлись в производительность БД. Хотя базы были мощные, их не хватало.
Естественное решение — добавить вторую шарду и маршрутизатор, потому что без него непонятно, куда направлять клиентов. На тот момент у нас была монолитная архитектура, поэтому добавить новую шарду не составило труда.
Мы стали добавлять ещё шарды, в них росло количество клиентских данных, поэтому нагрузка на БД тоже росла. Кроме того, стоимость дисков была огромной.
Чтобы выйти из ситуации, мы создали архивный слой хранения данных. Есть доклад Ильи Кайшаури про то, как мы в Сбере хотим мигрировать архивный слой хранения данных с Oracle в PostgreSQL в текущем и следующем году. Идея этого слоя заключалась в том, чтобы мигрировать туда данные старше года и хранить их на дешёвых железках. Удешевить СБОЛ в конечном итоге не получилось, так как мы остались на hi-end железках, зато получилось сделать другое: клиент при переходе в резервную шарду получает свои данные из архивного слоя, что делает этот переход для клиента почти бесшовным.
Проблемы при смене архитектуры
До шестой шарды был только монолит. Добавить новую шарду в монолите было, в целом, реалистично. Мы заказали железо, попросили ребят из поддержки сделать соответствующие настройки, накатили приложение, отправили туда клиентов, протестировали — и появилась новая шарда. Клиентов либо переносли из старых шард, либо направили новых на регистрацию. Шарда выросла, нагрузка на другие шарды снизилась.
Когда добавляли седьмую шарду, у нас уже появились микросервисы. Это отдельная платформа, стоящая рядом с монолитом. На тот момент на ней было около 70 микросервисов. Когда мы добавляли седьмую шарду, произошёл сбой, из‑за которого около 1000 заявок на кредиты были отклонены. Это произошло из‑за повторной отправки заявок. Если вы подаёте две заявки подряд, то вторую обычно блокируют в связи с подозрением на мошенничество. 1000 клиентов были заблокированы из‑за повторной отправки заявки, и их пришлось откатывать.
Такой проблемы не возникло бы в монолите, там было легко добавить шарду, везде стоял один и тот же приклад, параметры БД, схемы. А в микросервисах за каждый микросервис отвечает разный бизнес, служба поддержки.
Влияние оргструктуры
Когда нам понадобилась вторая резервная шарда, у нас было большее 200 микросервисов. Появились разные версии платформы — это некие базовые механизмы (библиотеки, приклады), которые нужны, чтобы строить свои микросервисные приложения. Поэтому при миграции со старой версии платформы на новую, нам приходилось пересобирать весь бизнес, проходить все тесты и прочее. При этом у каждой команды есть свой бэклог, и они как бы хотят заниматься бизнес-задачами. То есть в команде говорят: «Простите, у меня задача на 100 миллионов, придётся подождать». А когда у вас больше 200 сервисов, переход с одной версии платформы на другую занимает год или больше. Теперь представьте, что резервная шарда нужна к концу этого года, а вы об этом узнали в марте. В таких ситуациях оргструктура очень важна, потому что для бизнеса и айтишного руководства переход с одной версии платформы на другую — более приоритетная задача, чем новая резервная шарда. Из-за этого нам не дали доработать предыдущую версию платформы, которую можно было настроить, чтобы она работала на двух шардах. Это создало для нас определённые ограничения. Нам пришлось гнать бизнес вперёд, чтобы появилась вторая резервная шарда, потому что монолит и микросервисы живут вместе, и если вдруг в одной из шард что-то недоступно в микросервисах, значит не будет работать вся шарда. То есть вторая шарда могла запуститься, только когда в пром выйдет последний микросервис на новой версии платформы.
Получается, что оргструктура тоже внезапно на нас влияет, хотя, казалось бы, задача чисто айтишная.
Коммуникации (смежники)
Если вы спросите меня, что самое сложное в проектах, я отвечу — коммуникации. И не важно, о чём идёт речь: нужно ли вам договориться о требованиях или согласовать API. Критически важно, когда мы говорим про надёжность, выстроить процесс коммуникации со смежниками. Почему? Потому что вы друг от друга критически зависите.
Когда я пришёл в Сбер после универа в 2015 году, у меня была задача — реализовать механизм, похожий на circuit breaker. У нас это называлось «технологический перерыв». Его особенность в том, что он синхронизировался через базу данных. По классике механизм работает так: на сервер прилетают ошибки, если набралось X ошибок за Y минут, то сервер перестаёт отправлять запрос другому сервису, который эти ошибки прислал. У нас он работал точно так же, только ошибки в базе копились. Пока не накопится X ошибок за Y минут, все серверы обрабатывают запросы, а как только накопилось, то все сразу перестают обрабатывать.
Этот механизм был нужен по двум причинам:
Во-первых, чтобы остановить рост нагрузки на бэковую систему в самый плохой для неё момент, когда ей уже «плохо» и она некорректно обрабатывает входящие запросы.
Во‑вторых, бэковая система может проводить у себя обновления и накатывать ночью изменения, поэтому раньше мы выставляли «перерыв на обед». В это время приложение писало: «Извините, вклад можно открыть, но через два часа. Простите нас, пожалуйста, уважаемый клиент». Всё работало замечательно, пока однажды система процессинга, которая отвечает за транзакции по карте, не «встала». Клиенты начали постоянно перезаходить в приложении в надежде, что проблема уйдёт и баланс снова появится, но под такой нагрузкой система просто упала. Мы сделали выводы и перешли на circuit breaker.
Процессинг
Когда у вас есть смежники-контрагенты, от которых вы зависите, вы всегда должны с ними договариваться. Даже иначе: вы должны о них заботиться.
В нашем случае было так: к нам пришёл процессинг и сказали, что им не дают бюджет в этом году, поэтому не получается подготовиться к High Season и надо срочно что-то делать. Мы начали вместе думать и выяснили, что куча вещей работает неоптимально. Например, у клиента 5 карт. Он заходит в СБОЛ, совершает операцию по одной карте. После этого мы отправляем в процессинг запрос: «Дай нам балансы по всем картам». Но он же совершил операцию только по одной конкретной. Запрос баланса лишь по ней снижал нагрузку на процессинг на 20%.
Такую оптимизацию в монолите мы сделали просто: взяли одно место, сделали библиотеку кеширования, поменяли и всё заработало. В микросервисах эта задачка явно сложнее, так как необходимо разработать процесс, в котором каждая из команд подключит соответствующий механизм и настроит его.
Бизнес
Базово мы строим прогноз на конец декабря, гоняем нагрузочные тесты, «тыкаем пальцем в небо» и уточняем у экспертов. Они всегда помогают нам понять, что уже есть нехорошего.
Есть два дополнительных принципа:
Повелевай клиентами.
Работай с отложкой.
→ Вход по талонам
Есть сервис, который в своё время возник под кодовым названием «вход в СБОЛ по талонам». Это было следствием одного из инцидентов, когда мы не смогли справиться с нагрузкой от клиентов. Смежники не справлялись с дневной нагрузкой после выхода обновления, это приводило к тому, что «отложенный клиентский спрос» убивал уже наш бэкенд. И нам, и смежникам было так плохо, что завтра утром мы могли не подняться, поэтому сели командой в 9 вечера и решили накрутить на вход в Сбербанк-Онлайн rate limit. За ночь ребята написали библиотеку, и утром система снова была вполне работоспособна.
→ Мечта заплатить за телефон
Однажды мы столкнулись с проблемой: если вдруг недоступен сотовый оператор, их платёжный шлюз не работает, то клиент не может заплатить за свой телефон в Сбербанк Онлайн. Клиенты звонят в банк, растёт нагрузка на контактный центр и прочее. Пришлось практически уговаривать бизнес реализовать следующий сценарий: хранить платёжный запрос клиента с информацией об ошибке, а потом делать retry и оплачивать ещё раз.
Этот сервис не только повысил удовлетворённость клиентов, но даже при проблемах позволил сохранить количество платежей. Приложение говорило клиенту: «Дружище, через 15 минут мы всё оплатим, подожди, пожалуйста. Тебе нет смысла идти в другой банк, потому что у другого банка тоже не работает, причина не в нас».
Итоги
Вот основные принципы повышения надёжности системы:
Но важно помнить:
«Everything fails all the time» (Всё всегда падает)
Вернер Фогельс (Технический директор Amazon)
При решении любой задачи вы должны исходить из того, что система всё равно упадёт, и вам нужно на это как-то реагировать, то есть разработать стратегию. Мы в СБОЛе построили систему по принципу подводной лодки:
Система (микросервисы и монолит), как подводная лодка — полностью изолирована и поделена на отсеки. Если проблема в одном из отсеков (каналов), то мы перегородку закрываем, ничего страшного не происходит, все остальные каналы работают. То же самое при проблемах с разными сервисами.
И помните ключевой секрет отказоустойчивости:
Нет пользователей — нет проблем.
Как крайняя мера, ограничение количества пользователей всегда помогает.