За микросервисы и улицу — как мы внедряли новую инфраструктуру и почему она классная
С чего все начиналось
Когда мы запускали Клауд три года назад, у нас уже был продукт — VDS. Его инфраструктура была написана на Python, а бизнес-логика — на Erlang. Здесь же содержались виртуальный хостинг и панель веб-мастеров — разработка другой команды.
Первоначально стояла задача развивать Клауд как продукт со своей отдельной разработкой, для этого нужно было собрать команду. Erlang — редкий и специфичный язык, на рынке довольно мало специалистов, которые им владеют, к тому же они очень дорогие. По этой причине проще и логичнее было набрать команду для работы на более популярном стеке.
Нам хотелось собрать команду из fullstack-разработчиков, потому что у продукта достаточно сложная предметная область: нужно было понимать, как работает продукт на разных уровнях. Так, им было бы проще запускать новые фичи. Для того, чтобы реализовать задумку, сначала нужно было понять, как развивать и запускать новые сервисы и что делать со старыми.
Кроме желания оптимизировать команду, у нас была необходимость улучшить технические характеристики:
- Во-первых, в старой версии сервиса мы не могли увеличить время ответов API, а это напрямую влияло на скорость работы панели управления и на восприятие сервиса в целом.
- Во-вторых, из-за того, что Erlang непопулярный язык, на него было мало готовых решений и нам пришлось бы писать большую часть шаблонных решений самостоятельно, а не пользоваться тем, что уже использует комьюнити.
Выбор языка и подхода
Изменения мы решили начать с выбора нового языка: остановились на TypeScript и фреймворке Nestjs по двум причинам:
- У команды уже был опыт работы с этим языком.
- У нас было понимание, как искать ребят на рынке.
Далее нам нужно было выбрать стратегию развития продукта. Технически мы рассматривали два разных подхода к созданию Клауда на базе VDS:
Первый подход — монолитное приложение. Такую инфраструктуру несложно разрабатывать — она реализует все необходимые функции и работать так особенно удобно в момент, когда проект только запускается: команда пока небольшая и она не тратит время на дополнительные настройки развертывания, интерфейсов и взаимодействий между сервисами. Буквально всё находится в одном проекте, вы вносите обновления и дополнения в монолит — и это работает.
Второй подход — микросервисы. В этом варианте под каждую бизнес-сущность запускается отдельный сервис, который инкапсулирует в себя всю логику работы с конкретной функцией. Так, например, в Клауде для кластеров Kubernetes и балансировщика баз данных написаны свои микросервисы: каждый сервис инкапсулирует маленький кусочек продукта.
В разных компаниях могут быть разные принципы деления: где-то любят распределять ресурсы почти по атомарным сервисам, где-то наоборот, микросервисы достаточно большие, а внутри содержится много бизнес-логики.
Мы в Клауде делаем что-то среднее: инкапсулируем только то, что касается большого бизнес-блока.
Причины, по которым мы начали запускать микросервисы
- Мы понимали, что команда будет со временем увеличиваться и overhead на этапе внедрения микросервисов после завершения выльется в ускорение. За счет того, что все сервисы были отделены друг от друга, мы могли независимо доставлять и развивать их. Разные разработчики, когда реализуют какой-то функционал в разных частях систем, друг с другом не пересекаются. Такой подход стоит больше на этапе внедрения, но дешевле потом, когда ты с этим работаешь и есть хорошая компетентная команда.
- Нам не хотелось переписывать то, что было раньше: решили рядом создавать новый продукт для того, чтобы сэкономить ресурсы. Так, старые элементы кода мы заменяли новыми написанными частями системы и переключали, соответственно, работу панели и API на новые сервисы. Этот процесс продолжается до сих пор и будет какое-то время продолжаться: работы нам хватит еще на полгода точно.
Микросервисы намного сложнее, чем монолитные приложения с точки зрения их доставки. Здесь требуется квалифицированная команда DevOps, которая сможет правильно настроить все этапы доставки изменений.
Запуск первого микросервиса
Мы решили запустить первый сервис в тестовом режиме и посмотреть, насколько это удобно и какие проблемы решает. Одним из таких сервисов были наши стандартные облачные серверы. В системе, еще до обновления, запросы для получения списка серверов выполнялись достаточно долго, особенно это касалось крупных аккаунтов — запрос там висел по несколько секунд. Была задача это оптимизировать.
В результате внедрения даже первого микросервиса мы получили ускорение в десятки раз: для крупных аккаунтов, в которых, допустим, несколько сотен VDS, запрос раньше грузился 7-10 секунд. После внедрения нового сервиса, нам удалось сократить время загрузки до нескольких десятков миллисекунд.
Такой подход решил задачу бизнеса, когда все работает быстро и слаженно. Одна часть запросов теперь уходила в микросервисы, другая — в монолитное приложение. У нас тогда еще не было API Gateway: еще одну авторизацию для нового сервиса мы реализовывали просто рядом.
Далее команда занялась полноценным проектированием. Описали, как будет выглядеть продукт через год или полтора. В результате получили полноценную карту развития микросервисов, по которой и стали двигаться. Все новые сервисы мы сразу запускали на ноде, использовали тот же подход, что и вначале: понемногу выносили старые и запускали рядом новые.
Первые трудности
Кроме запуска микросервисов нам требовалось наладить сразу несколько взаимодействий: между самими сервисами и между сервисами и панелью управления. Для этого нужно было приложить много усилий, в итоге у нас появилась схема:
Для всей автоматизации мы используем GitLab CI/CD: отдельная команда девопс занималась и занимается тем, что помогает нам настраивать автоматизацию и доставлять изменения в сервисах на любое из окружений. Все работает в пару кликов из интерфейса GitLab и настроено очень удобно.
Нам требуется проверять, что клиент действительно имеет право выполнять тот или иной запрос: нужен механизм авторизации и аутентификации, при том, что сервис не один. Система должна понимать, в какой из микросервисов следует отправить клиентский запрос — этим занимается API Gateway. Снаружи система для клиентов выглядит так, будто это единый рабочий интерфейс, внутри же он идет в определенный микросервис и там получает нужные данные.
Что нам дало внедрение микросервисов
Мы постоянно собираем фидбэк с наших клиентов: видим, насколько сильно он улучшился. Но было сложно объективно оценивать пользовательскую реакцию в контексте только микросервисов: мы делали сразу много обновлений, в том числе, новый дизайн панели.
Тем не менее, клиенты отмечают, что продукт стал работать стабильнее — это положительно повлияло на уровень удовлетворенности.
К тому же внедрение микросервисов позволило сократить тайм-ту-маркет: доставка обновлений стала дешевле и почти в четыре раза быстрее.
Вообще все наши ожидания оправдались. Мы ставили перед собой несколько целей:
- Технически ускорить работу сервисов.
- Обеспечить высокую скорость релизов — это было требованием бизнеса.
Мы должны оперативно вносить любые изменения: нам стало намного проще разрабатывать и оптимизировать методы, писать их так, чтобы решения работали без перебоев.
Конечно, были технические сложности: нам пришлось настраивать сложную систему авторизации для того, чтобы совместить старое монолитное приложение с новыми микросервисами, но реальных бэдкейсов не было.
Сейчас мы пришли к схеме, где старый монолит — просто один из микросервисов в новой системе: мы особо не отличаем его от любых других наших сервисов.
Как поменялось отношение команды к работе
Мы смогли получить контроль за продуктом, потому что первый монолит поддерживался другой командой. Новые сервисы мы пишем сами и любые изменения вносим самостоятельно. Поскольку релизить обновления теперь можно оперативнее, к нам чаще приходят новые классные задачки — в принципе работать стало интереснее.
Мы не засиживаемся с одной задачей надолго, быстро делаем и запускаем обновления, дальше — идем к новому. Это драйвит команду: ей самой интереснее развиваться.
Я не знаю, что именно вам дало внедрение микросервисов, но под красивой оберткой у вас лютый "колхоз". Из-за атак на вас, я перенес основные свои сервисы на DO (о чем сейчас не жалею). Ну так вот, у них есть функционал App Platforms, я довольно быстро на него подсел, так как деплой из гита - это очень круто и не зависит от окружения. Увидел у вас бету Apps, стало интересно попробовать. Но жесткая привязка к языкам и платформам, все это похоронило хорошее начинание. Ну почему вы не можете сделать нормально?! Ведь пример у конкурента есть!
Здравствуйте, Виталий! Очень полезная обратная связь по Apps. Если вам не трудно, можете закинуть эту идею на голосование по ссылке (https://timeweb.cloud/my/ideas)? Если ее поддержат другие пользователи, разработка возьмет ее в приоритет и сделает как в DO 💪 По поводу атак, время действительно было непростое. В нас в течение двух месяцев прилетало до 1,5 Тбит, но мы справились. Мощно укрепили сеть по всем локациям, практически став магистралом. Скоро будет про это отдельный кейс кстати, уже почти готов
Наняли фуллстеков чтобы писать микросервисы на JavaScript.
Directed by Robert B. Weide.
😎
Мем - класс!!