Привет, Хабр и хабровчане! Меня зовут Владимир Григорьев, я директор по архитектуре Газпромбанка. Сегодня хочу рассказать про фронт-платформу розницы Газпромбанка, в которой мы реализовали системный подход для выставления продуктов в цифровых и традиционных каналах продаж. При проектировании платформы учитывался многоканальный подход обслуживания клиентов.  Например, в бизнес-процессе оформления кредитной или дебетовой карты клиент может начать заполнять заявку в мобильном банке и по каким-то причинам остановиться на полпути, но у него сохраняется возможность продолжить оформление. Система сохраняет черновик заявки клиента, присылает ему смс-напоминание со ссылкой на черновик, либо сотрудник из call-центра звонит и напоминает клиенту о возможности завершить оформление по этой заявке. Как все устроено Сейчас встретить работу платформы «в дикой природе» можно везде: звонок в контакт-центр, вставленная карта в банкомат, перевод денег, операции в мобильном или интернет банке — всё идет через  фронт-платформу. Если взглянуть верхнеуровнево, то наша платформа немного напоминает слоеный пирог. Верхний слой —  слой каналов. Они могут находиться как в контуре банка, так и вне      его. В каждом канале есть клиентская часть (с ней взаимодействует клиент)      и бэковая (то, что развернула команда канала на своих системах и выставила      API). Ниже идет защитный слой,      так называемый WAF (Web Application      Firewall),  с помощью которого осуществляется безопасная публикация      универсальных сервисов вовне. Платформенный слой — наша главная «начинка» этого пирога. На этом уровне реализована комплексная бизнес-логика в универсальных сервисах (УС), которые не зависят от канала. УС из данного слоя обмениваются информацией непосредственно с системами провайдеров (бэк-системами), связываясь с ними через интеграционный механизм (слой ниже) или через распределенное хранилище In Memory Data Grid по принципу cqrs. Стоит отметить, что на этом же уровне разместился Identity Provider Платформы, с помощью которого происходит аутентификация и авторизация пользователей. Слой интеграции. Собирает отдельные простые сервисы банка в универсальную сервисную модель. Взаимодействие возможно посредством IBM MQ и через IMDG — DB Tarantool, реализованного коллегами из VK (ранее Mail Group). Слой провайдеров сервисов. Строго говоря, это уже не платформа, но для большего понимания и завершенности процесса пусть будет. Это бэковый слой, заключающий в себе разного рода приложения банка (учетные, справочные, платежные системы и другие), которые выступают провайдерами простых («fine      grained») сервисов банка. Идентификация  Основными пререквизитами для создания Платформы были переход на единый IDP во всех каналах и аналитический MDM. IDP создан на классическом для таких решений ПО OpenAM. Клиент вводит свои учетные данные для аутентификации, получает легкий токен (SID), далее выбирает сценарий, по которому пойдет его взаимодействие с сервисами банка (получить продукт, информацию о счете и т.д). Внутренние сервисы банка не работают с SID (он небезопасен и формируется при прямом взаимодействии с клиентом), поэтому его необходимо заменить на полноценный JWT. Подмена происходит в IDP. В самом JWT будет информация о разрешениях и запретах для этой сессии. При каждом обращении к сервису Платформы OpenIG будет прочитывать JWT, понимать, что он не скомпрометирован, и разрешать те или иные действия с собой. При проектировании сервисов мы использовали концепцию «стаканов» — каждый сервис закрывается своим OpenIG, размещенным максимально близко к защищаемому сервису (на том же сервере/поде). При такой реализации невозможно вызвать публикуемый сервис без проверки OpenIG, так как при вызове любого сервиса сначала запрос попадает на nginx, который переадресовывает запросы на OpenIG для проверки авторизации. Добавлю, что если сервис является публичным и не содержит в себе информации, относящейся к категории тайн, то для вызова такого сервиса токен не нужен. Точнее, при обращении к нему проверка не будет производится. Дополнительно в целях защиты от DDos-атак должно быть прописано ограничение на nginx публикатора сервисов, например, ограничив количество запросов с одного адреса к опубликованному ресурсу. Аналитический MDM Следующий пререквизит — аналитический MDM. Мастер данных по клиентам банка для розничного домена — вещь крайне необходимая и полезная. Тема систем MDM не нова и описана в нескольких статьях на хабре (например: https://habr.com/ru/company/navicon/blog/260927/). Если коротко, мы решили пойти по этому же пути и внедрить решение, которое бы хранило в себе «золотую запись» по клиенту. Системы, получая запрос от клиента, сначала проверяют его наличие у нас в MDM и только после того, как он не будет найден, дергают сервис «create/update client», передавая данные определенного формата. Далее МДМ будет заниматься нормализацией этих данных, сводить несколько профилей клиента в один (если есть необходимость), создавая «золотую запись». Когда одной из систем понадобятся актуальные данные по клиенту, они знают где и как их взять. Что происходит под капотом MDM? На изменение каждого поля у каждой системы есть определенный вес, и если пришло два изменения одного поля по одному клиенту, то оба весовых показателя сравниваются и в «золотую запись» попадает изменение с наивысшим весом. Условно, если пришло изменение по клиенту из канала «Дашборд» (это офис обслуживания клиентов, и, следовательно, там сотрудник получил информацию напрямую от клиента), его вес будет выше, чем, например, у изменения из каналов «Экосистема» или «Партнеры», где данные не верифицировались сотрудниками или взаимодействие с клиентом было удаленным. Если автоматически провалидировать изменения система не смогла, то на этот случай есть внимательный Data Steward. Он берет такие кейсы и отвечает на вопрос, «стоит ли вносить изменения по клиенту или это новый клиент». Когда изменения по клиенту были акцептованы и внесены, в MDM формируется обратный поток, который сообщает информацию по этим изменениям. Все системы, где фигурирует данный клиент, получают актуальные данные. Мы используем для этих целей событийный подход, все изменения отправляем в топик Кафки, а потребители вычитывают эти изменения. В среднем на прохождение целого пучка разных правил и процесс дедупликации уходит до трех часов. То есть с временным лагом в 3 часа мы получаем актуальную «золотую запись» по каждому клиенту банка. Я есть КРУД При проектировании микросервисной архитектуры мы приняли решение пойти по пути информационной нарезки сервисов (cqrs — принцип разделения запросов). Каждый сервис обязательно должен исполнять минимум одно из действий над своей сущностью из аббревиатуры CRUD (create, read, update, delete). Также сервисы с бизнес-логикой должны быть отделены от сервисов технических (core services). У этих сервисов разные команды, разные биоритмы, и развиваются они по разному. Например, технический сервис более статичен и обеспечивает оркестрацию запросов с фронта к сервисам с бизнес-логикой (продуктовым сервисам). В свою очередь, сервис с бизнес-логикой может релизиться хоть каждый день, что не повлияет на работу всей платформы. Добавляя новые сервисы в ландшафт, мы не усложняем логику всей системы. Очевидно, что такой подход вносит некоторые ограничения для команд, которые хотят использовать нашу платформу, но плюсов гораздо больше, чем ограничений. Если порассуждать и рассмотреть альтернативные подходы (например, один из наиболее известных — шаблон «Разбиение по бизнес-возможностям»), вырисовываются такой вполне реальный риск. Допустим, мы разрабатываем сервис «Получение карты клиентом» для главной страницы мобильного и интернет-банка. Через некоторое время приходит команда кредитных карт, которая хочет переиспользовать этот сервис для подачи заявки на кредитную карту. Но им необходимо добавить несколько полей, например «Сумма», «Место работы» клиента и так далее. Нам это уже не так актуально, мы отправляем эту задачу в «бэклог бэклогов» и спокойно идем есть печеньки.  Очевидно, команде кредитных карт такой подход не по душе, и они форкают наш сервис, добавляя нужную функциональность. В итоге в платформе плюс один сервис (так и вижу, как где-то в параллельной вселенной будущего сидит и плачет архитектор Платформы). Далее другая команда проводит аналогичный форк — и так еще несколько раз. В какой-то момент количество данных сервисов становится невыносимо большим, а некоторые, возможно, даже дублируют функциональность на 99%. Все эти сервисы опираются на одну и ту же сущность в учетной системе, и когда они начинают эволюционировать и развиваться, команды могут легко забыть, с чего все начиналось. И, конечно, нелегко понять, какая команда и как именно использует свой сервис. Все это усложняет и удорожает нашу платформу. Именно для того, чтобы избежать хаотичного раздувания платформы и усложнения ландшафта, мы вычленили ряд core services. Core services Подача заявки клиентом в любом канале. Когда продуктовый сервис производит онбординг (разворачивается на нашей Платформе), он, выполнив определенные процедуры, получает возможность выставлять информацию о своем продукте во всех подключенных каналах. Платформа, в свою очередь, фиксирует каждое заявление клиента и хранит его нужное время, например, 2 часа, месяц или 3 года - это настраиваемый параметр. Если клиент не закончил заполнение заявки на сайте, например, у него будет достаточно времени чтобы вернуться, завершить начатое и отправить заявку.  Информация о клиенте и его продуктах Создаем и редактируем эту информацию. Добываем данные о клиенте и его продуктах по определенным стандартам, кэшируем данные. Системы-провайдеры данных не перегружены частыми обращениями, и у них нет необходимости обкладываться адаптерами для каждой новой «нестандартной системы». Технические функции. Авторизация и аутентификация клиента. Мониторинг и логирование. Служебные сервисы: медиаконтент, управление фичами, оповещение о недоступности и т.д. Командам не нужно тратить ресурс на организацию нефункциональных требований, все это на себя берет платформа , где уже взрощена экспертиза по этим направлениям. Коммуникация с клиентом Взаимодействие реализуется по основным каналам связи - СМС/Push/Mail.  Все это доступно «из коробки» продуктовым сервисам, которые выполняют условия онбординга: Единый формат данных для всех сервисов-потребителей. Стандартный шаблон сервисов для наполнения бизнес-логикой. Единые конвенции по разработки сервисов, библиотеки (springboot,      hibernate, apache      commons, swagger, java-jwt, log4j, liquibase, apache.pdfbox, lombok, Junit, redux*, react*, isomorphic-fetch). Middleware Cache Для доступности информации в наших дистанционных каналах 24/7 мы используем middleware cache. Это in Memory Data Grid — БД Tarantool. Этот кэш наполняется от поставщиков данных через CDC и витрины ETL. Также происходит атомарное наполнение кэша через ESB-шину. Из-за имеющихся ограничений для некоторых поставщиков мы используем гибридный подход. Строим витрину на репликах систем поставщиков данных, которые, в свою очередь, наполняются через CDC. Это позволяет избежать команде IMDG более глубокого погружения в смежные системы и оставить логику наполнения витрин в зоне ответственности поставщика. Поставщик данных (бэк-система) сам подготавливает необходимые процедуры для наполнения витрины, а техническая учетная запись запускает их поочередно. После их выполнения стартует процесс обогащения кэша. В целевом виде планируем использовать CDC и только стриминг событий. Вместе с запросом на получение клиентских данных сервису приходит директива о том, как именно их нужно достать. Основных стратегии три: Первая и целевая для нас — зайти в кэш и проверить наличие данных. Если временной лаг по актуальности данных превышает пороговое значение, идти в АБС. Вторая — мы не идем в АБС совсем и только проверяем кэш на наличие нужной      информации (например, когда важна скорость получения данных, номер карты      или продукт банка; обязательное условие при этом — данные редко изменяются). Третья, когда мы не идем в кэш и стучимся в АБС за нужной информацией (например, запрос кодового слова клиента). Так как системы, содержащие эти данные, высоконагружены и порой немножко легаси, невозможно обогащать актуальной информацией кэш с производственного стенда, поэтому данные идут с реплик. У такого подхода есть минусы, ведь мы получаем серьезную зависимость от самого процесса репликации. Если репликационный стенд по каким-то причинам отстанет, мы получим отставание в кэше, не попадем во временной лаг актуальности и сильнее просадим боевой стенд по большому количеству обращений. Но такой риск перекрывается высокой производительностью. Помимо клиентских данных в кэше находится информация по валютным курсам, которая, как мы знаем, изменяется в режиме онлайн. Для этих целей реализовано две очереди передачи информации в кэш: быстрая и медленная. Быстрая нужна для отдачи данных по курсам валют в режиме онлайн в дневное время, а медленная используется как резерв, а также предназначена для отдачи курсов валют в ночное время. Потребность в кэше постоянно растет, например, актуализировать данные по картам клиентов необходимо раз в 1 минуту, а по депозитам и того чаще — раз в 15 секунд. На графике выше мы видим, что запросы попадали в кэш в 70% случаев (от всех запросов в Платформу). Также видим трехкратный рост количественных показателей за 2021 год (левый столбец — количество обращений в тыс/мес). Актуальность кэш в нашем случае очевидна. Улучшения показателей утилизации кэш — одна из основных задач розничного бизнеса. Tеchstack Техстек платформы вполне стандартный для таких решений, в случае необходимости он расширяется. Мы ориентируемся на свободно распространяемое ПО. Планомерно внедряем практики CI/CD и переносим сервисы на Openshift. В заключение Наша платформа растет. Постоянно появляются новые сервисы и продукты. Почти 70% всех заявок на дебетовые и кредитные карты проходят через Платформу. Проект НДБО (новый мобильный и интернет банкинг) более чем в два раза увеличит количество обращений к платформе. На данный момент мы фиксируем более 75 запросов в минуту, а новый нагрузочный профиль (+ НДБО) формируем из нагрузки свыше 160 обращений. В этом посте я рассказал, как устроена наша фронт-платформа в целом. Если вам интересно было бы узнать более детально про тот или иной аспект нашей реализации, пишите в комментариях. Освещу эту тему подробнее.