Чем быстрее идея воплотится в новый проект, тем больше шансов занять нишу, завоевать лояльность пользователей и, как следствие, стать успешнее конкурентов. Ускорить разработку и сделать её более гибкой и управляемой помогает микросервисная архитектура. Вместе с Дмитрием Горчаковым, руководителем отдела разработки РЕД-СОФТ, мы разобрали плюсы и минусы микросервисов, а ещё рассмотрели сценарии, как компании приходят к их внедрению.  

Что такое микросервисная архитектура

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

Альтернатива монолиту — микросервисы.

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

Впервые о микросервисах заговорили ещё в 2000-х годах, когда в США произошёл кризис электронных технологий. Тогда был бум на интернет-сервисы, но никто всерьёз не задумывался о масштабировании, а оборудование не было таким мощным. В один момент крупные сервисы не смогли справиться с возросшей нагрузкой и потеряли своих пользователей и инвестиции. Это привело к переоценке многих вещей в индустрии ПО, и уже к началу 2010-х микросервисы сформировались как концепция архитектуры. А к 2014-ому их начали внедрять крупные компании вроде Netflix, Amazon и Twitter.

Минусы микросервисного подхода

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

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

  • Каждый микросервис может использовать тот язык программирования и те технологии, что удобны команде, которая его разрабатывает. С одной стороны, это плюс — какие-то фреймворки и языки лучше заточены под конкретные вещи. Если мы делаем сервис обработки изображений или машинного обучения, можем не заострять внимание на технологиях монолита, а выбрать решение под задачу. С другой стороны, это минус — нужно как-то конфигурировать все микросервисы между собой и поддерживать «зоопарк» технологий. 

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

  • Сложности развёртывания. Чтобы требования по отказоустойчивости выполнялись, микросервисы нужно развёртывать на отдельных серверах. И здесь не работает подход: «Берём приложение, ставим и запускаем». Нужны системы оркестрации и деплоймента. 

Плюсы микросервисного подхода

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

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

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

Как компания понимает, что пора внедрять микросервисы

Глобально можно выделить два подхода к разработке приложений. Первый — когда зрелая компания с опытным архитектором и командой разработки решает написать сервис, который будет выдерживать большие нагрузки. В этом случае уже есть понимание, что монолит не справится с поставленной задачей, нужен другой архитектурный подход. Примеры — «ВКонтакте», «Одноклассники», Mail.ru. Когда они планируют новые продукты, уже понимают, как будут их строить. 

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

Признаки, что пора внедрять микросервисную архитектуру:

  • Рост нагрузки. У любого монолита есть предел масштабирования, так как он стоит на одной машине. Конечно, машины можно докупить, но эта опция не бесконечна и довольно затратна. Рост стоимости здесь не линеен, и в конечном счёте приведёт к пределу. Скажем, процессор в два раза мощнее, будет стоить не в два, а в четыре раза дороже. 

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

  • Градация в данных. Появляется какой-то модуль, доступ к которому должен быть быстрее, чем к остальным. Например, мы хотим, чтобы в интернет-магазине доступ к популярным товарам стал быстрее. Делать быстрее доступ ко всем данным (корзине, каталогу и др.) слишком дорого. Вместо этого мы можем выделить под популярные товары отдельный микросервис. Он будет строиться на других технологиях и позволит ускорить доступ. 

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

Как перейти на микросервисы

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

Каких-то академических подходов к «распиливанию монолита» нет. Всё зависит от особенностей системы и поставленной задачи. Предположим, мы хотим выделить систему подписок в монолите. Вот один из сценариев, как это может быть:

  • Шаг 1. Выделяем отдельный узел и переносим туда логику. При необходимости делаем рефакторинг кода общей системы, чтобы она была меньше связана с другими модулями, а мы могли вынести её в отдельный узел. Разрабатываем способ взаимодействия.

  • Шаг 2. Живём «двойной жизнью», пока данные реплицируются. Убеждаемся, что всё работает правильно.

  • Шаг 3. Полностью отключаем функциональность от монолита и переносим её на микросервисы.

По такому же принципу можно работать и с другими функциональными модулями монолита. 

Пример микросервиса Java

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

Всего пять модулей, но чтобы эти пять модулей правильно работали, добавляются ещё обслуживающие модули:

  • модуль маршрутизации, который будет управлять запросами;

  • балансировщик нагрузки, который будет следить, чтобы модель котировок не отказывала;

  • service registry, который поможет команде понять, какие сервисы есть, как работают, какие порты слушают и т.д.;

  • сервис конфигураций, который будет конфигурировать наши пять модулей;

  • сервис логирования и журналирования, который поможет быстро обнаруживать проблемы;

  • сервис трассировки, который позволит определить, где сейчас запрос;

  • сервис сбора метрик, который покажет, что и как у нас работает, какие бизнес-параметры выполняются.

То есть помимо пяти сервисов, которые выполняют какую-то полезную работу, нам нужны ещё узлы, которые будут играть обслуживающую роль. 

Вместо заключения: частые ошибки при работе с микросервисами

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

Для тех, кто хочет разобраться в микросервисах

15 июля у нас стартует курс «Микросервисы и API на Java и Kotlin». Вы узнаете, как писать микросервисы и работать с приложениями на одних из самых популярных языков программирования. Познакомитесь с Java-фреймворком для разработки модулей микросервисов Spring Boot и прочими полезными инструментам и подходами. 

Посмотреть программу и записаться

 

Комментарии (13)


  1. eldog
    01.07.2022 17:58
    +7

    Вот с этим утверждением можно поспорить:

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


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


    1. AlexSpaizNet
      02.07.2022 19:41

      В монолите очень сложно следить за тем кто и что делает и кто какие модули импортит.

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

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

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


  1. ProstakovAlexey
    01.07.2022 23:06
    +1

    В java, python и др. Есть модули, пакеты. Разве это не способ боротся со сложностью кодовой базы? Выделить пакет отдельной команде и другим в него не ходить. Подключать через мавен. Чем такой подход плох? Микросерсисы хлопотрое дело, пока настроиль консул, мониторинг, облачную конфигурацию, кафки и прочее устанешь уже. У кого сотня микросервисов, как вы живете, страдаете?


    1. shadek
      02.07.2022 14:49

      Одно не исключает другое. У нас 200+ микросервисов, 2/3 используют общие пакеты/модули, которые делают отдельные команды. Кафки / хашикорп и все остальное так же нужно и для монолита да еще на разных контурах. Хлопотность микросервисов сильно преувеличена. Но согласен, это не серебряная пуля и не всем надо.


    1. kalombo
      03.07.2022 20:36

      Ну вот представьте всю экосистему Яндекса из сотен сервисов и тысяч программистов в одном монолитном репозитории. Как думаете где страданий больше?


      1. ProstakovAlexey
        04.07.2022 09:25

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


        1. kalombo
          04.07.2022 11:13

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

          Микросервисы тоже внедряем, ну чтобы как в Яндексе

          Вот и спрашиваю как у остальных

          Понимаете, нет универсального решения. Зачем вы равняетесь на яндекс, если у вас не тысячи программистов, а 5? А вообще у вас классический случай: "О, я услышал про волшебное чудо решение, которое решает все проблемы, давайте затащим его к нам" Когда вы внедряете микросервисную архитектуру нужно понимать, зачем вы её внедряете, чтобы быть как Яндекс? Звучит сомнительно. Если у вас всё прекрасно с монолитом, то делая микросервисы вы создаете себе кучу лишней работы непонятно зачем. Сам сталкивался с таким, когда тимлид, начитавшись про микросервисы, за каким-то чертом вынес rest-апи сервиса в отдельный сервис и поставил между ними очередь для синхронизации. Выхлоп - ноль, а зато столько работы и проблем сразу появилось. А вот когда у вас начинают возникать проблемы, ну представьте, допустим 50 человек работают над монолитом и каждый делает свой реквест, попробуй всё это проконтролируй. Или стало невозможно деплоить это монолитище, каждый раз танцы с бубнами. Или например, у вас есть возможность нанять программистов, но на другом стеке, вам выгодней по трудозатратам сделать 2 сервиса(5 программистов на джаве и 5 на питоне), чем собирать команду из 10 джавистов. То тогда есть повод задуматься о каком-то решении, необязательно сразу микросервисы, может вы сумеете как-то порешать проблемы малой кровью, разбив на модули. В общем вот вам тезис https://martinfowler.com/bliki/MonolithFirst.html


      1. acmnu
        04.07.2022 10:02

        ИМХО, Java хорошо переживает тысячи разрабов в одной репе благодаря всей этой сложившейся культуре с иерархией архитектор-->team lead --> senior --> middle --> junior.

        Плюс там паттерны заточены под переиспользование кода с минимальными последствиями.

        Хотя усилий требуется не мало, конечно.


    1. acmnu
      04.07.2022 09:31
      +1

      У кого сотня микросервисов, как вы живете, страдаете?

      • Микросервисы это не столько архитектурная, сколько организационная проблема.

      • Нужна команда SRE. Программистам хода на продакшен нет. Никогда.

      • Нужен хороший CI/CD

      • Нужна строгость в сборке и деплойменте: -snapshot.jar недопустим (он так-то никогда недопустим, но кого это останавливает)

      • Как можно больше статических проверок контрактов. Как раз в Java c этим прекрасно (хотя я не Java прогер, могу ошибаться)

      • Как можно больше асинхрона для уменьшения связности.

      • SDET и QA Automation.

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

      Есть мифы, частично упомянутые в статье:

      • Сервис дискавери это сложнА! - Нет, не сложно, поскольку там очень шаблонированный код, особенно в наше время. Да и в большинстве случаев все ограничивается k8s и terraform и не доходит до Consul и Zookeeper

      • Мониторинг сложнее чем в монолите - Нет, не сложнее. Если не делать архитектурных глупостей, то мониторинг можно шаблонировать и выйдет примерно как с монолитом. А еще раскурить ELK и OpenTelementry. Ну и главная проблема мониторинга едина для всех подходов: необходимо каждый параметр описать и определить диапазоны, а на это уходит дикое количество времени.

      • Деплоймент это сложнА! - Для программистов да, хотя не то чтобы сложно, а непривычно и ненужно. Но для этого есть отдельные специалисты: SRE, DevOPS, QA

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


  1. mafia8
    02.07.2022 01:43
    +3

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


  1. arTk_ev
    04.07.2022 13:06

    Если сервисов меньше 10 то можно сидеть на синглтонах. Если их меньше 50, то нужен gi-контенер для сервисов. Если их еще больше, то уже нужно разбивать на слои Model, View, VM.

    Основная проблема микросервисов, в том что они противоречат SOLID, поэтому микросервисы обязаны быть независимы друг от друга, без иерархии, вечноживущие и всегда доступны. Ну и не допускать "ад синглтонов" и никаких "хелперов"


    1. acmnu
      04.07.2022 13:46

      вечноживущие и всегда доступны.

      Можно эти свойства переложить на отдельные сервисы, например добавив MQ, или сделав связку MQ+ServerLess.


      1. arTk_ev
        04.07.2022 15:08

        Хотя микросервисы позаимствовали с веба, как там реализуют не очень знаком.

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

        Контейнеры еще позволяют очень удобно тестировать и удалить все #ifdef в коде, которых и не должно быть в принципе.

        Но непонятно как их масштабировать дальше, когда их уже сотни.