Как мы переезжали с монолита на микросервисы

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Привет! Я тимлид команды «Добро» в «Сравни.ру», мы занимаемся разработкой сервиса по подбору кредитных продуктов. 

Сервис, над которым мы работаем, помогает нашим клиентам подобрать кредитные продукты с высокой степенью одобрения. Для этого мы придумали алгоритм, который аккумулирует необходимый объем данных, обрабатывает их и подбирает кредитные продукты от банков, которые с высокой долей вероятности одобрят заявку конкретного пользователя. Нетипичное название команды («Добро») произошло от слова «одобрение». 

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

С чего всё начиналось

На момент принятия решения о переезде проект «Сравни.ру» существовал уже около семи лет. Сайт был написан на .NET и представлял собой один большой монолит. Как можно догадаться, чтобы выкатить очередное обновление, приходилось немного пошаманить. У нас было несколько админок, в которых нужно было время от времени перезагружать данные. Все данные собирались из одной базы, выполнялся экспорт, и они обновлялись пачкой. Это занимало кучу времени. Вместо этого мы хотели получить реал-таймовые админки (когда поправил раздел — и он моментально обновился на сайте).

Еще одной проблемой было то, что проект получился большим, долго компилировался, на это могло уходить по несколько часов. У нас был релизный цикл. Например, через две недели мы выпускаем новую версию сайта — и туда войдут такие-то фичи по таким-то разделам. 

Мы же хотели перейти к другой схеме: разбить всех на продуктовые команды, каждая из которых отвечает за свой раздел, отдельно релизит и может быстро проводить итерации. Даже если они выкатят код с багом, должна быть возможность это быстро исправить или откатить на предыдущую версию. И это никак не должно затрагивать другие разделы сайта, потому что процесс отката или фикса мог занимать несколько часов, а хотелось, чтобы это занимало максимум минуту. 

В какой-то момент нам надоело тратить кучу времени, и мы захотели перейти к более гибкой разработке и коротким итерациям, быстрее релизить разные фичи, проводить A/B-тесты и так далее. К тому же сайт морально устарел с точки зрения пользовательского опыта — и много что нужно было переделывать. Тогда-то мы и решили, что раз уж мы всё переделываем, то надо распиливать наш монолит на отдельные сервисы и переходить на более гибкий стек, который позволяет делать итерации гораздо быстрее. 

Из технологий выбрали Node.js для серверной части, React — для фронтенда и MongoDB — в качестве базы данных, а для хостинга — Azure и Яндекс.Облако. Перевести хотели в облако, чтобы всё крутилось в Kubernetes. Это открывало дополнительную универсальную схему: так и команды, и DevOps-инженеры могли легко это всё поддерживать.

Как мы переезжали

Проект начали делить по разделам. Логически хотелось вынести и фронтенд, и бэкенд в ведение команд, чтобы у них была полная свобода действий: как и что релизить, что использовать и так далее. Но очень скоро эти разделы стали разрастаться и угрожали превратиться в новые монолиты. 

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

Начали использовать MongoDB в качестве системы управления базами данных, но возникли проблемы. В части сервисов нужно было производить сложные выборки и вычисления. По философии и некоторым технических ограничениям MongoDB нам не очень подходила, так как приходилось делать «хитрые» агрегации на большом объеме данных. Например, считать процентные ставки. Это всё работало медленно, и мы поняли, что инструмент не подходит для таких задач. Сейчас MongoDB мы также используем, но PostgreSQL лучше подходит под наши задачи с точки зрения логики. Чтобы не грузить базу, часть расчетов мы вынесли либо на клиентскую, либо на серверную часть.

Что касается деплоя, то, как я сказал раньше, мы сделали несколько репозиториев под разные проекты. Например, репозитории под наш сервис по подбору кредитов выглядели так: credit_selection_frontend, credit_selection_service, credit_selection_backoffice.

Реализовали всё это через TeamCity. Заходя в TeamCity, любой разработчик или тестировщик может выкатить один сервис или сразу несколько. Выкатывается всё либо в тестовый, либо в продакшен Kubernetes. Это дает возможность изолированно тестировать функционал сразу в нескольких микросервисах. Добавляем в несколько микросервисов и смотрим, как это вместе работает и как будет выглядеть для пользователя. Как минимум это посмотрят тестировщики, а в некоторых случаях — продакт-оунеры. Грубо говоря, тестовые стенды создаются двумя кликами мыши через TeamCity. 

В конце концов мы перенесли всё в Kubernetes, это позволило легко создавать и деплоить новые сервисы. Сейчас у нас есть несколько нод Kubernetes для разных задач.

Проблемы и их решение

При переезде на микросервисную архитектуру мы поняли, что нельзя целиком переписывать код, так как это огромный проект, у которого могут быть свои баги и недоработки. Поэтому пришлось выкатывать всё по частям и переписывать код по разделам. 

В процессе переезда запросы шли в монолит. В монолите был код, который эти запросы роутил либо в свои обработчики, либо на микросервисы, если запрашиваемый раздел был уже на новой архитектуре. Проблема была в том, что, например, когда мы выкатывали новый микросервис, могла произойти ошибка в таблице маршрутизации урлов. Это приводило к тому, что мы выкатывали сервис, а он не работал. 

Из-за того что проксирование шло через монолит, это возвращало нас к необходимости снова пересобирать проект несколько часов. Пользователи не могли нормально использовать сайт в течение этого времени, что для нас было критично. 

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

Немного про тестирование и деплой

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

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

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

Для непрерывной интеграции и деплоя мы долгое время использовали TeamCity, сейчас потихоньку переезжаем на GitHub Actions.

Что в итоге?

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

Сейчас внедряем ML и тоже деплоим в Kubernetes. Но об этом расскажем в следующий раз. Буду рад ответить на комментарии и вопросы!

Источник: https://habr.com/ru/company/sravni/blog/652203/


Интересные статьи

Интересные статьи

Или как поменять фундамент старого дома, чтобы он не обвалился Лет 10 назад мы выбрали 2-ю версию Python для разработки нашей обучающей платформы с монолитной архитектурой. Но с те...
Одна из самых важных (на мой взгляд) функций в Битрикс24 это бизнес-процессы. Теоретически они позволяют вам полностью избавиться от бумажных служебок и перенести их в эл...
В этой статье мы рассмотрим, как система управления 1С-Битрикс справляется с большими нагрузками. Данный вопрос особенно актуален сегодня, когда электронная торговля начинает конкурировать по обороту ...
Однажды, в понедельник, мне пришла в голову мысль — "а покопаюсь ка я в новом ядре" (новым относительно, но об этом позже). Мысль не появилась на ровном месте, а предпосылками для нее стали: ...
В интернет-магазинах, в том числе сделанных на готовых решениях 1C-Битрикс, часто неправильно реализован функционал быстрого заказа «Купить в 1 клик».