Идет 2020 год. Если вам нужно пояснение, что такое микросервисы — лучше потратьте свое драгоценное время на что-то другое. Но если вы впечатлены историями успеха о микросервисах и хотите нырнуть в "панацею" с головой — продолжайте читать. Прошу прощения, будет немного длинновато (не очень, прим. переводчика).
Хотя мысль об этом витала уже некоторое время, необходимость ее записать возникла недавно, после захватывающего разговора с парой человек. Меня пригласили для того, чтобы достичь кворума при решении одной весьма интересной проблемы: "что такое микросервисы и должны ли мы следовать этой архитектуре для нашего ПО?".
По первой части вопроса договорились легко, а вот вторая встала весьма остро. Через пару минут общения часть фактов была собрана:
- Есть желание использовать микросервисную архитектуру в будущем продукте, надо это как-то утвердить.
- Кворум был в большей степени нетехническим, чем больше он переходил в "техническую плоскость", тем более неуместным он становился.
- Длинные паузы и отсутствие вопросов подразумевали незнание функционала как веб-сервисов, так и микросервисов.
Я их не осуждал за отсутствие знаний о функциях веб-сервисов или о следствиях работы микросервисов. Собеседники, конечно же, весьма превосходили меня в работе в своей отрасли. Но они хотели запрыгнуть в микросервисы без оценки возможных последствий!
Впервые о микросервисах я узнал еще в 2013 году, это был ролик на YouTube, где пояснялась архитектура сервисов Netflix. Было весьма впечатляюще, но я пропустил все без сожаления, поскольку это было слишком сложно для меня, человека, который тогда только начал постигать принципы разработки. Скоро это стало навязчивой идеей, поскольку на новом проекте объявили о внедрении микросервисов. Разработка проекта была увлекательной, он до сих пор остается лучшим по кодовой базе из тех, что попадали ко мне.
Честно говоря, широкие возможности модульной разработки были где-то далеко от меня, и я просто добавил дополнительный уровень сложности, будучи невежественным разработчиком, скрывавшимся от DevOps. Спустя пять лет я уже работаю с совершенно новым продуктом и другими людьми. У меня куча проблем, возникших из-за плохо разработанных микросервисов, приправленных тактикой девопсов-любителей (девляпсов?, прим. переводчика). Пелена довольно скоро спала, обнажив хрупкость микросервисов. Также я начал смотреть на всю эту архитектуру более опытным взглядом. Было поздно, но лучше поздно, чем никогда.
Видя, что микросервисы играют роль как главного героя, так и главного злодея, я сознательно убедил себя стать "адвокатом дьявола". А если вы архитектор или разработчик, выбирающий микросервисную архитектуру по умолчанию — придержите коней и задайте себе несколько вопросов.
Ваше приложение достаточно большое, чтобы дробить его на микросервисы?
Давайте признаем это. Не все приложения достаточно велики, чтобы их можно было разбить на более мелкие сервисы. Микросервисы, как следует из их названия, предоставляют набор небольших обособленных сервисов, каждый из которых выполняет некую роль. В идеальном мире ожидается, что каждый сервис будет сам по себе полноценным приложением.
На картинке выше представлено сравнение "стоимость строчки кода" между микросервисами и монолитным приложением. Микросервисы дороже, даже в простом случае, поскольку есть минимальная цена ресурсов, необходимых для работников и оборудования. Об этом должен думать каждый, а если вас это не заботит, возможно, вам вообще не стоит принимать такие решения.
Никто не спорит, что в будущем размер кодовой базы может вырасти, а это может добавить новый уровень сложности, но также не стоит забывать о том, что правильно разработанный код всегда можно перевести на микросервисы при приближении к пороговому значению.
Нужно ли на самом деле масштабировать отдельные компоненты приложения?
Предположим, что владелец продукта обратился к вам с идеей системы управления для автоматизации отдела кадров компании, в которой работает от 10.000 сотрудников. Технический энтузиаст внутри вас ответит мгновенно: микросервисная архитектура.
Конечно, это граничный случай, но общий смысл вы уже уловили! Одно из основных преимуществ использования этой архитектуры — простота масштабирования отдельного компонента. Можно найти множество приложений, в которых этот принцип сработает, но нужно ли это вашему приложению?
Есть ли транзакции, распределенные между сервисами?
Возможно, это наиболее сложное и стратегическое решение, ведь транзакции, охватывающие несколько сервисов, отвечают за всю архитектуру. Обработка транзакций в разных сервисах означает совместную блокировку между сервисами, часть таких взаимоблокировок трудноотслеживаемы и создают состояние гонки. Эти плавающие ошибки причиняют вред сервисам, а иногда портят кровь и инженерам.
Cервисы REST не имеют состояния по определению, а также не должны участвовать в транзакциях, которые проходят по нескольким сервисам. В мире высокой производительности двухфазный коммит (2PC) — ненужное зло. Шаблон SAGA добавляет еще один уровень сложности, к которому вы не будете готовы.
Микросервисы создают возможные проблемы целостности данных из-за того, что по своей сути настойчиво предлагают децентрализованное управление данными. В монолитном приложении можно обновить очень многие вещи в одной транзакции, а для обновления этих же данных в микросервисах требуется несколько заходов, в то время как распределенные транзакции не приветствуются (по уважительной причине). Поэтому разработчики должны знать о проблемах целостности, а также выяснять, как выявить отсутствие синхронизации, прежде чем писать код, о котором потом пожалеют. Martin Fowler
Возможно ли иметь распределенные по сервисам транзакции?
Да, конечно.
Стоит ли делать цепочку действий поверх сервисов без состояния (stateless)?
Возможно, не стоит!!
Есть ли нужда в частом общении между сервисами?
В обычном монолитном приложении каждый экземпляр микросервиса предоставляется в виде модуля системы. Связь между модулями работает в памяти с задержкой, близкой к нулю. Внедряя микросервисы не стоит забывать, что связь между сервисами перешла от транзакций в памяти к передаче по проводам.
Есть много проверенных и протестированных решений, но цена у них одна и та же — задержка. При переходе к микросервисам задержка вырастает от наносекунд до микросекунд. Попробуйте представить, что есть три сервиса, передающие данные по сети. Предполагая, что каждый вызов сервиса занимает 100мс (не очень быстро под нагрузкой), вы потратите 300мс только на сеть.
Следует учесть, что некоторые приложения тесно связаны с компонентами и сервисами по своему устройству. Дополнительные издержки связи могут привести к катастрофическим последствиям в приложениях, обрабатывающих данные в реальном времени. Попробуйте представить задержку связи в хирургическом костюме или в системе управления воздушным движением!
Кое-что ещё
- Добавленная сложность — конечно же, она не может быть определена в абсолютном значении, но ее можно сравнить относительно чего-либо. Несмотря на то, что микросервисы изначально разрабатывались для уменьшения сложности за счет разбиения приложения на более мелкие части — их архитектура более сложная в развертывании и обслуживании.
Следует помнить, что усредненная организация в IT не обладает такими же навыками, как команды инженеров Netflix. mike_pfeiffer
Цена распределенных систем. Микросервисы — распределенные системы с молекулярностью. Но распределенность имеет свою цену. Монолит был бы развернут на большой виртуалке или в некотором предварительно сделанном контейнере. Но микросервисы должны разворачиваться независимо (в идеальном мире) на нескольких виртуалках или контейнерах. Конечно же, они бывают небольшими по размеру, но это стоит также учитывать, и помнить, что я еще не начал говорить о затратах на управление и обслуживание.
Внедрение DevOps может быть как полезным, так и вредным. DevOps — проверенное и широко распространенное решение, но если вы работаете в маленькой компании, создание команды DevOps может принести больше вреда, чем пользы. Но одно можно сказать точно — нельзя поддерживать и управлять микросервисами без команды DevOps.
Сильная связность — некоторые приложения сильно связаны по своей природе. Разбиение на микросервисы, чтобы «вписаться» в архитектуру, будет катастрофическим.
Отсутствие опыта. Отсутствие опыта имеет решающее значение для любой проблемы, и оно не ограничивается только SOA. Но когда дело доходит до микросервисов, это может стать решающим фактором. Если вы разворачиваете приложения в неправильном порядке или произойдет сбой и зависимый сервис упадет — будет уже поздно.
Сквозное тестирование. Типичное монолитное приложение позволяет запускать и запускать тест практически мгновенно. Наличие нескольких служб с взаимозависимостью задержит тестирование без жизнеспособной оркестровки.
Хаотичные контракты на данные. Разработка и хранение контрактов на данные внутри команды сильно отличается от их распространения среди команд. А когда вы работаете с микросервисами, ваша команда может не находиться в одном регионе, не говоря уже об использовании одного и того же языка программирования. Выработка контрактов с данными для особых нужд будет стоить вам времени и места.
Устаревшая кодовая база — давайте будем честными. Для большинства из нас работа с устаревшей кодовой базой — это повседневная деятельность. Это хлеб с маслом большинства организаций. Быстро меняющиеся технологические достижения ставят нас впереди всех, но и в то же время они изолируют нас от устаревшей кодовой базы. Вы уверены, что только что разработанный фреймворк, использующий RabbitMQ, хорошо работает с устаревшим приложением, работающим на AIX?
Устранение неполадок — каждый сервис будет иметь свой собственный набор файлов журналов для анализа. Больше сервисов = больше файлов.
Заключение
Я здесь, чтобы сказать "Не используйте микросервисы"?
Конечно же, нет!!
Микросервисы заслужили известность. Они решили проблемы, которые считались неразрешимыми. История Netflix по применению микросервисов вдохновила многих. И список определенно не останавливается на Netflix. Uber, SoundCloud и гигантский Amazon — вот некоторые примеры, которые у всех на слуху. И не думайте, что истории успеха ограничиваются только потребительскими приложениями. Я имел непосредственный опыт работы с американским гигантом здравоохранения и был очарован возможностями дизайна, каждый раз, когда открывал исходный код.
Если бы вы доверились этой идее пять лет назад — я бы не осуждал вашу доверчивость. Время было другое, но теперь все, что можно сделать — быть честным. Сейчас 2020 год. Мы достаточно обожглись, и вокруг нас слишком много авгиевых конюшен. Внедряя бездумно архитектуру микросервисов, вы просто превращаете свой плохой код в плохую инфраструктуру.
Мне нравятся увлеченные программисты, я сам такой когда-то был таким, да и все еще есть. Они преданы тому, что делают, и переходят все границы, чтобы решить свою проблему. Но вы не можете так же энергично принимать решения, которые могут стоить вам и организации целое состояние, извините за резкость. Микросервисы не должны быть вашей архитектурой приложений по умолчанию. Это не серебряная пуля, которую вы искали. Сохраняйте равновесие с KISS и YAGNI.
Как сторонник технологии и энтузиаст, вы имеете право что-либо предпочитать. Однако то, что показывает вас с лучшей стороны — способность выбирать прагматично, когда варианты находятся между «правильным выбором» и «вашим любимым выбором».
amaksr
Почему-то в статьях всегда обсуждают крайности, микросервисы против монолита. Почему не разбивать приложения на естественные куски с минимальным числом связей, назвать их сервисами, и иметь только плюсы обоих подходов?
Vilaine
Если вы сможете разбить приложение на cohesive сервисы, то можно предположить, что вам не придётся преодолевать обычные проблемы веб-сервисов (ныне микросервисов).
khim
Потому что хайп движет миром.
Если вы предложите просто «разбить приложения на естественные куски с минимальным числом связей» — то вам покажут 100500 незакрытых фич-реквестов и никто ничего разбивать не будет.
А вот если вы покажете решение, которой может решить сразу все мировые проблемы сразу и будуте говорить достаточно убедительно — ресурсы, может быть, и удастся получить…
marshinov
Вероятно, потому что «не модно». Сам задаюсь этим вопросом пару лет.
nekt
Очень многие пилят «микросервисы», когда как на практике придерживаются сервисной архитектуры, которой уже сто лет в обед будет — en.wikipedia.org/wiki/Service-oriented_architecture
Нормальные микросервисы — это когда не 5, не 10 сервисов, а 1000-5000 на тот же размер кода. И все это независимо мастштабируется в контейнерах для полноценной утилизации ресурсов. На такую крайность мало кто идет.
creker
SOA и микросервисы практически ничем и не отличаются друг от друга. Никто в своем уме не может предложить адекватного определению микросервисов, потому что его не существует. Так же как не существует адекватных технических определений bigdata, nosql, data lake и прочего, что напридумывали. Единственное осязаемое отличие SOA и микросервисов культурное и организационное, но не техническое. И нет никаких жестких требований по количеству, когда SOA переходит в микросервисы. Все попытки показать отличия SOA и микросервисам выглядят довольно смешно, т.к. часто приводят в пример ESB, XML, SOAP, контейнеры. Как-будто смена протокола и шины обмена кардинально меняет парадигму. Как было распределенное приложение с асинхронной модель передачи информации, так и осталась. Просто пришел прогресс и появились технологии по-лучше, но сам подход не менялся и никуда не делся. Выросли только масштабы, до которых некоторые (и только некоторые) довели этот подход. Масштабы, которых раньше просто не было.
vedenin1980
Почему? Микросервисы обычно подразумевают автоматический оркестратор (запуск и остановку инстансов в основном без участия человека), несколько экземпляров большинства инстансов, слабую связность (потенциально все инстансы должны работать в независимых виртуальных машиных или docker контейнерах).
SOA может реализовываться как микросервисами, так и большими ручными сервисами-приложениями.
creker
И все это никак не противоречит SOA, потому что микросервисы всего лишь SOA. Люди пытаются выделить микросервисы во что-то свое уникальное, но оно таким не является, отчего адекватного определения и не видно. Поэтому люди и цепляются за всякие глупости вроде контейнеров, devops (еще одно бессмысленное нечто), протоколов обмена информацией, которые не означают ровно ничего, кроме того, что SOA сегодня делают на контейнерах и rest. И почему-то кому-то пришло в голову назвать это микросервисами.
vedenin1980
А разве кто-то с этим спорил? Однако обратное неверно — не всякая SOA архитектура это микросервисы.
VolCh
Есть же адекватное: должно хватить двух пицц, чтобы накормить команду, способную поддерживать один микросервис.
lear
Две пиццы это на какой срок?
Какие именно пиццы? Диаметр? Вес? Калорийность?
Если это был сарказм, то я не понял)
А так… Смешивать техническое и человеческий фактор прожорливости — не самая лучшая идея.
Две пиццы 35-40см в диаметре я могу легко съесть за часов 5, хотя я не такой и большой (около 85кг).
VolCh
За раз, за один приём пищи типа ланча, больших, видимо. Дословно не помню, но когда читал в голове чётко картинка сложилась — человек 6, 8 максимум. Если не справляются, то или микросервис надо дробить, или перестать называть его микро.
antonkrechetov
Миллениалы изобрели модульность.