Как мы делали микросервисную архитектуру для проекта
на 500к пользователей

Вступление
Всем привет!

Я — Михаил, руководитель филиала в Питере.

Сегодня хочу поделиться опытом построения микросервисной инфраструктуры проекта, который за 3 года вырос с 10 000 активных пользователей до 500 000.

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

Что такое микросервис?

Микросервис — небольшая обособленная часть проекта, которая решает конкретную бизнес-задачу. И только ее. Каждый микросервис имеет интерфейс (чаще всего API), при помощи которого можно пользоваться его функционалом.

Далее из этих частей, как из конструктора, собирается полноценное приложение.

Преимущества

  • каждый микросервис изолирован от ошибок других сервисов. Таким образом, неполадки в одном из них не повлияют на работоспособность системы в целом;

  • микросервисы могут быть реиспользованы в других проектах;

  • микросервисы не зависят от определенной платформы, для различных частей системы можно использовать различный стэк;

  • удобство доработки и масштабирования. При неизменном интерфейсе можно безболезненно переделать все внутренности;

  • упрощение деплоя приложения (деплоится не весь проект, а только определенный микросервис);

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

Недостатки

  • на стадии начальной разработки приложения достаточно сложно определить набор микросервисов и их ответственность;

  • добавляются дополнительные «накладные» расходы на взаимодействие между микросервисами (транспорт и т. д.);

  • сложно придерживаться общего принципа разработки между микросервисами (использование общих библиотек и их версионирование и поддержка);

  • трудно производить комплексное тестирование приложения со всеми микросервисами.
Как и зачем разбивать монолит на микросервисы?
На заре развития нашего филиала в компании уже работал проект-монолит, позволяющий обучать около 10 тысяч пользователей. Мы проанализировали текущую ситуацию в проекте и поняли, что, разобрав наш монолит на микросервисы, мы решим многие проблемы динамично развивающегося проекта. Основные из них:


  1. Низкая отказоустойчивость.

  2. Большие риски при разработке новых фич.

  3. Сложность совместной работы с проектом для территориально разделенных команд.

  4. Большие накладные расходы на поддержку.


Поэтому мы активно приступили к проектированию нашей будущей инфраструктуры. Для начала было принято решение выделить три микросервиса:


  • storage (для централизованного хранения файлов);

  • users (для удобного управления пользователями);

  • feedback (для переиспользования другими проектами бизнес-потребности в комментировании/оценивании материала).
Решение о выделении именно этих микросервисов принимали на основе трех факторов: степени требований к надежности и масштабированию этой части системы, сложности отделения от монолита и необходимости реиспользования. Разумеется, что разработка каждого из них укладывалась в один спринт.

Таким образом, простейшая схема первой версии выглядела так:
схема микросервисной архитектуры
Чуть подробнее
USERS

Из основного приложения была вынесена вся информация о пользователях в отдельную базу, и вся логика переехала в микросервис пользователей. Такое решение позволило уменьшить основной проект на 30 %! Большая часть бизнесовой логики завязана на использовании пользователей. А это значит, что другие микросервисы стали получать информацию не из главного приложения, а из микросервиса пользователей. Также такое решение позволило легко масштабироваться горизонтально. Недостаточно вычислительной мощности? Просто добавляем еще один инстанс микросервиса — и дело в шляпе!

STORAGE

На выделение логики по работе с файлами в отдельный микросервис натолкнула мысль о расширяемости данного решения. Данный микросервис знает все, где и в каком месте искать нужный файл. Недостаточно памяти? Просто добавляем дисковое пространство и конфигурируем данный микросервис. Хотим распределенного хранения данных? Не вопрос, пару строк конфигурации — и у вас уже распределенная система хранения файлов!

FEEDBACK

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

Поэтому решили выделить этот микросервис одним из первых. Оценка учебного материала, обращение в техподдержку, система комментариев — за все это отвечает данный микросервис.
Что-то пошло не так
Любой разработчик уровня middle и выше, понимающий теорию разбиения на микросервисы, может посмеяться над первой версией нашего проектирования. Скорее всего, он укажет, что это никакие не микро-, а достаточно крупные сервисы, которые нужно разбивать еще мельче. Сравнивая наши желания и потребности, мы хотели сделать сразу и правильно, с одной стороны, быстро — с другой. Нам казалось, что компромисс найден...
Очень быстро мы поняли, что USERS и FEEDBACK в нашем случае нужно разделять еще больше. Разумеется, увеличивая изначальную оценку и сроки проекта. Думаю, что не нужно цитировать менеджера, управляющего проектом в тот момент. Даже самые вежливые комментарии были нецензурными =) Но в итоге мы смогли найти взаимопонимание и сделали вторую версию нашего проекта:
микросервисная архитектура
AUTH

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

ACL

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

COMMENTS

Функционал, вынесенный из FEEDBACK as is.

FEEDBACK

Был переосмыслен в целом после нагрузочного тестирования. Под нагрузкой 20 000 пользователей лайки ставились более 5 секунд, сообщения в чат техподдержки могли идти более 15 секунд.

Так как на этом функционале были построены критичные бизнес-процессы, пришлось серьезно поработать над его оптимизацией, скоростью и отказоустойчивостью. Мы реализовали для него шину событий с несколькими потоками, которая позволила работать с обратной связью в режиме онлайн без серьезных задержек в транспорте. Кстати, сам транспорт, отправку сообщений пользователю и сервис техподдержки мы тоже выделили в отдельные микросервисы уже в следующей версии.
Поехали!
В таком виде спустя месяц работ проект был запущен. Все шло хорошо, мониторинг показывал не более 30 % нагрузки.

И в этот момент пришла хорошая новость. Количество пользователей нашего проекта в ближайшее время должно было быть увеличено до 200 000. Ну что ж, отличное испытание, решили мы и снова засучили рукава.
Версия 3
Третья, работающая на данный момент, версия архитектуры выглядела так:
микросервисы в обучении
Как видно, она не слишком отличается от второй. Оказалось, что для стабильной работы под нагрузкой, увеличенной на порядок, нам достаточно найти узкие места и масштабировать их в соответствии с требованиями. Основные проблемы, с которыми мы столкнулись, — это:

  1. Тормозящая в нескольких кейсах БД. Решалась оптимизацией и горизонтальным масштабированием.

  2. Большой трафик, особенно внутри сети. Решалась масштабированием балансиров, кэшированием на уровне сервера и т. п.

  3. Большие накладные расходы на транспорт между микросервисами в нескольких кейсах. Решалась оптимизацией запросов/ответов.

Видно, что все проблемы стандартны для растущего проекта. Изменений в саму архитектуру вносить практически не пришлось.
Еще пара кейсов
Кроме примера с ростом нагрузки — главным для нас испытанием, приведу еще пару показательных кейсов.

Видеорелиз

Мы работаем в корпоративном сегменте. Одна из самых больших проблем в нашем направлении — долгая доставка контента с момента передачи заказчиком до момента назначения обучения пользователю. В среднем на разработку сценария курса, отрисовку контента, согласование и бюрократию уходит около двух недель.

Для этого полностью автоматизировали процесс доставки в виде цепочки инструментов, где не надо ничего пересылать или передавать: Редактор -> Публикация -> CD -> Назначение через админку и разработали инструмент доставки. В результате снизили показатель time to market до 5 часов. К примеру, когда на уровне корпорации требуется донести до всех сотрудников какую-то важную информацию, можно быть уверенным, что уже сегодня все сотрудники ее получат.

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

Изменение стэка

Помните, мы говорили об использовании разного стэка в микросервисной архитектуре? Так вот, все наши приложения на тот момент работали на PHP 7.1. В какой-то момент пришло бизнес-требование о дополнительном шифровании данных, которое можно было бы решить только с версии PHP 7.3 beta на тот момент.

Тут наш шаблон монолитного мышления начал трещать по швам =) Обновлять систему до новой версии, поймать и фиксить кучу ошибок во всем проекте и работать с нестабильной версией PHP мы точно не были готовы.

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

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

imagespark
Мы создаем создаем уникальные образовательные платформы для корпоративного и вузовского обучения
tel
+7 (495) 640-95-25
e-mail