company_banner

Микросервисы VS монолит: баттл адептов

    Монолитная и микросервисная архитектуры — два диаметрально разных подхода. Во время круглого стола на конференции DevOps Live 2020 столкнулись адепты этих архитектур, которые в формате баттла искали ответы на самые актуальные вопросы. Избыточны ли ресурсы на каждый микросервис? Есть ли необходимость в постоянном рефакторинге? И как грамотно организовать рабочее место?

    Адвокатом микросервисов выступил Алексей Шарапов, а обвинительную речь зачитал Андрей Булов. Оба сотрудники Deutsche Telekom IT Solutions — стратегического подразделения крупнейшей в Европе телекоммуникационной компании Deutsche Telekom — и не новички в обсуждаемом вопросе.

    Андрей Булов: Я работаю в довольно крупном энтерпрайзе, в котором берут свое начало молодые стартапы. Побывал в разных ролях: архитектора, девелопера. С 2016 года начал писать на микросервисах.

    С тех пор я невзлюбил паттерн «Microservice as a goal», которым грешат многие энтерпрайзы, и стал пропагандировать здравый смысл. Честно говоря, я считаю, что микросервис и текущая разработка — это что-то типа Spotify в Agile: все хотят внедрить, но не все понимают, зачем это нужно.

    Тема этого мини-баттла родилась  чуть ли не из кухонного спора. Я устал всем доказывать, что микросервис — это не Грааль,  не панацея, и готов поделиться своим мнением.

    А еще я люблю лямбды, и считаю, что микросервис — это некое переходное звено.

    Алексей Шарапов: На данный момент я являюсь DevOps евангелистом. То есть хожу и очень громко всем говорю: «Давайте делать DevOps!». Я в разработке с 2010 года. Занимался разработкой фронтенда и немного бэкенда. С 2015 года влюбился в DevOps и DevOps-практики. Стараюсь заниматься ими ежедневно и приносить счастье нашим разработчикам.

    Я работаю с Андреем в одной компании. Это крупный энтерпрайз. И у нас есть исключительно микросервисные проекты, которые я полюбил всем сердцем. Поэтому я выступлю адвокатом микросервисов. 

    Андрей Булов:  Начнем с меня. Почему микросервисы — это плохо? Во-первых, потому что это очень дорого. Почему-то считается, что у всех, как у Google, есть куча намаринованных маленьких серверов, в которые можно засунуть маленькие сервисы, и все будет прекрасно работать.

    На самом деле, вам придется купить облако и Кубер, и во всей этой виртуализации будет работать Docker, в котором зашиты ОС Java-машина, Application Server и микросервис, раздающий три строчки. А вы будете греть воздух всей этой чудесной инфраструктурой.

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

    Тот же монолит или мелкая галька прекрасно выполняются на Bare Metal, не требуют особых ресурсов, Application Server JVM. И внутри себя они общаются по бинарным внутренним протоколам, байтики бегают по серверу: все прекрасно и довольно быстро работает. 

    Да, можно писать не на JVM, но все равно выходит недешево.  Микросервисы обходятся дорого с точки зрения перформанса, скорости разработки и работы внутри.

    Алексей Шарапов: На все это могу ответить, как человек, занимающийся инфраструктурой в крупных компаниях последние несколько лет, что мы можем делать очень много классных вещей. В первую очередь, ограничивать минимум. Если на наш сервис нет нагрузки в спокойном состоянии, можем сделать ему минимальные ресурсы. Мы должны содержать Kubernetes-кластер, какие-то дополнительные сущности, но запуском внутренних компонентов можем управлять очень-очень тонко. И если в какой-то момент нам на определенное время нужны сущности, мы можем использовать CronJob. А еще Openfaas, о чем часто забывают. Мы не греем наш кластер ненужными сущностями, а запускаем только то, что необходимо. 

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

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

    Не стоит забывать и о том, что когда мы запускаем на Bare Metal, нужно какое-то общее окружение, с которым мы работаем. Если все это учесть, получается даже чуть больше, чем в кластере Kubernetes.

    Андрей Булов:  Микросервисы — это штука, которая требует некоей Java-команды и постепенного обучения. То есть вы девелопите какой-то микросервис, и в нем может постепенно меняться его бизнес-контекст. Многие забывают, что помимо обычного советского рефакторинга, который нужно делать практически каждый день, микросервисы еще требуют бизнес-рефакторинга. Если в монолите вы можете просто порефачить модули и сделать git push force, как тимлид или девелопер, то в микросервисах вам придется договориться с другими командами, с другими людьми и, например, перенести функционал из одного микросервиса в другой. 

    Мой личный опыт: когда разрастается какой-нибудь важный микросервис типа Order-микросервиса, или Booking-микросервиса, который выполнял 90% функционала приложения, по-моему, немного теряется смысл. Нам требовался временный рефакторинг в заказной разработке или в бизнесе. Довольно трудно продать людям, которые заведуют деньгами, что нам нужно еще пару спринтов, чтобы перекроить бизнес boundaries наших микросервисов. Потому что с первого раза (и со второго, и с третьего) мы не смогли понять этот контекст, зато теперь научились.

    Я это лично продавал продуктоунерам. Это занимательно. Если уж вы отважились на микросервисы, всегда помните о том, что рефакторинг не закончится никогда. Он как ремонт, и вам нужно будет всегда со всеми договариваться. Закладывайте хотя бы процентов 20 времени исключительно на это.

    Алексей Шарапов: С мыслями о рефакторинге я не согласен. Если API меняется от версии к версии, возможно, это включает в себя несколько проблем, которые больше на совести девелопера, разрабатывающего эту часть. Либо нужно запланировать, что не стоит вводить постоянные изменения, включая новый функционал микросервисов.

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

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

    Как всегда, когда собрались архитекторы, происходит рефакторинг ради рефакторинга. Но нужен ли он здесь на самом деле, или хочется впихнуть то, что в формат микросервиса впихивать не нужно? В монолите мы привыкли к тому, что можно что-то переписать, поменять модуль,  и все классно! Но чтобы отрефакторить монолит, которому 20 лет (а я с таким сталкивался в реальном мире, это не сказки), только для того, чтобы разобраться, как это сделать, нужно полгода. И это без учета времени на необходимые изменения.

    Андрей Булов:  Микросервисы — copy & paste driven development. Согласно идеологии микросервисов, в них не должно быть общих зависимостей, кроме какого-нибудь спринга, или общих либ. Но почему-то все забывают о том, что когда микросервисы пишутся для энтерпрайза, пусть и не очень кровавого, у него есть enterprise-specific вещи. А есть еще базовые, типа общей аутентификации, общего логирования, общих доменных объектов.

    В зависимости от упорства адептов микросервиса, мы будем либо копипастить весь этот код между нашими микросервисами, либо сделаем библиотеку, либо вынесем это в отдельный микросервис.

    Я прекрасно помню кейс, когда мы деплоимся на какой-то init или prod, у нас собираются нормально десять микросервисов, а одиннадцатый —  бабах! — падает. Мы забыли туда скопипастить наш общий user-объект, в котором есть пермиссии. И с матами, конечно, все это дело правим.

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

    Очень трудно определить бизнес-контекст такого микросервиса. Например, аутентификация — это бизнес или не бизнес? А общие объекты, которые валидны для всего приложения, или для всего энтерпрайз-ландшафта? И начинаются всякие интересные спекуляции.

    За это я микросервисы не очень люблю.

    Алексей Шарапов: В этом моменте я с тобой согласен, но не во всем. Мне нравится подход, когда библиотека выносится отдельно, и все ее куски делаются при помощи CTRL-C — CTRL-V.  С июля мы начали новый проект, в котором изначально используется микросервисный подход. И я слышал что-то подобное от наших архитекторов: либо мы копируем, либо выносим в библиотеки.

    Но подключать библиотеку стоит, наверное, на стадии сборки самого микросервиса. А мы сейчас говорим про наш энтерпрайз Agile, и в этом нет ничего страшного. Это просто зависимость, которая будет выполнять близкий функционал. Либо — к чему мы пришли только спустя четыре месяца работы — стоит выносить этот функционал в отдельный микросервис. 

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

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

    Андрей Булов:  Собственно, именно поэтому: в микросервисах нет единого хорошего стандарта, а есть набор практик и адепты, каждый из которых агитирует за свое. Если микросервис разрабатывает программист или команда программистов, вы получите свой уникальный стиль микросервиса с такими вещами, как POST vs PUT (холивар на кухне), и рассуждениями о том, какие ошибки мы возвращаем при валидации, какое возвращаем время и в каком стиле мы возвращаем API. 

    Это требует либо постоянного ревью: чтобы пришел архитектор или лид-девелопер и вставил руки в нужное место, либо нужен общий гайдлайн на проект. Но опять же, общих best practices для микросервисов, к сожалению, нет. Адепты спорят друг с другом. И ты думаешь: «Хм, разработчик Василий так любит двухсотый код возвращать, надо учесть эту специфику. А этот, наверное, 404 бросит. Ведь тут не сервер упал, просто у него код ошибки такой». Либо требуется централизованное управление, и тогда теряется весь смысл микросервисов. У тебя получается команда с многими модулями, которые просто деплоятся отдельно, и архитектор ходит и пишет для них гайдлайны. 

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

    Алексей Шарапов: А как вообще жить без документации? Я бы начал с этого, потому что я себе такого не представляю. Да, мысль, может быть, чуть-чуть испорчена энтерпрайз-сложным миром, большим и тяжелым. Но даже несмотря на микросервисную инфраструктуру и архитектуру, мне нравится документация. Под ней можно понимать не подробный талмуд о том, как мы должны написать микросервис, а описание общих частей. 

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

    По поводу всего остального. Во-первых, инфраструктура as a code становится проще. То есть деплой становится everything as a code, а все части деплоя, инфраструктуры и самого кода вы можете посмотреть в Гите. Разработчику проще, когда он деплоит какое-то количество микросервисов, и отлавливает эти ошибки быстрее. Ему не нужно лезть в тяжелый монолит, рассматривать его и пытаться понять, что происходит. Он понимает, что происходит от написания первой строчки до попадания на ProdStage, и на каждой отдельной части. 

    Плюс выпуск происходит намного быстрее, и ему легче свериться с документацией. Ему не нужно разбираться с внутренними взаимодействиями, с тем, как работает система. Он написал свою часть. Видит, с чем это все вместе работает, и может выпускать этот кусочек. С Андреем я согласен в одном: в команде должны быть люди, которые понимают, что они делают. Даже несмотря на кровавый энтерпрайз, они должны понять, что они создают микросервис по определенным законам. И все будет круто до тех пор, пока люди соблюдают установленные правила, хотя бы из взаимоуважения.

    Андрей Булов:  Да, давайте наймем команду космонавтов, которая нам все хорошо сделает.

    О, мое любимое. 

    На самом деле картинка — это практически реальный ландшафт системы и реальный кейс. Прибегает ко мне заказчик, говорит: «Слушай, там бага. Из Гуя на проде неправильно заказ считается для такой-то модели машинки для немецкого рынка. Для остальных все хорошо работает. Вот тебе логи, прод не трогай. На деве это воспроизводится. И вот тебе данные».

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

    С точки зрения вычислительных мощностей, поднять у себя такое количество докеров, конечно, можно, но тогда тормозить будет зверски. Если мы подключаемся к какому-нибудь Куберу и удаленно пробрасываем порты, конечно, оно может сработать. Но тогда получается, что один девелопер блокирует все девовское окружение, а другие сидят, курят бамбук или девелопят локально. Либо нам нужно много-много окружения, иначе необходимо много-много серверов. Что возвращает нас к первому вопросу: все это совсем не дешево. 

    А в-третьих, чтобы банально сграбить данные со всех этих микросервисов, из БД, мне нужно залезть в каждый, вытащить какие-то данные и посмотреть, совпадают ли они. Потому что у нас констрейнтов нет. А потом нужно это все себе залить, или залить на дев, поднять и посмотреть, чтобы заработало. Да, чтобы еще у меня port forward не умер в самый интересный момент, потому что процесс растянут во времени.

    Поэтому дебажить микросервисы я «люблю» очень сильно!

    Алексей Шарапов: Андрей прямо по больному прошелся. Конечно, дебажить микросервисы довольно-таки сложно. Но, на самом деле, команда должна просто привыкнуть к освоению новых инструментов. 

    В мыслях о port forwarding я с Андреем абсолютно не согласен. Если приходится пробрасывать огромное количество каких-то сущностей в единицу времени, наверное, мы опять говорим о том, что у нас слишком большое количество взаимодействий. Нужно вообще прекратить это дебажить, поднимая какие-то локальные контейнеры. Либо, необходимо иметь достаточное количество неймспейсов. Понимайте изначально, во что вы вписываетесь. Да, это может быть дорого. Вы можете поднять какой-нибудь свой minikube. 

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

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

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

    Андрей Булов:  Видимо, я морально устарел в микросервисах.

    Есть еще вот такой интересненький кейс:

    У нас есть микросервис со своими бизнес-контекстами, сервис, который делает Order, сервис, хранящий в себе Vehicle. Есть API GW, есть GUI. К нам приходит продактоунер и говорит: «Эй, ребята, мы принимаем заказы на машины, и теперь занимаемся отделкой салона».

    И начинается парад независимости. Это когда команды внедряют у себя один параметр и проносят его через все независимо друг от друга. 

    А потом начинается игра: давайте все это дело проинтегрируем! Мы возвращаемся к предыдущему слайду: как это дебажить?

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

    Это абсолютно реальный пример: нам никуда не деться от того, что придется пронести бедный параметр Vehicle Cover через все микросервисы и базы. Давайте это сделаем и помолимся, чтобы все программисты микросервисов назвали это правильно, соблюли чудесный capital letter, сделали везде одинаковый тип, воркчар был правильным, все это прошло ревью архитектора и т.д.

    В монолите это сделать довольно легко: открываем идею, смотрим, даем кому надо по рукам — профит! В микросервисах придется побегать между командами.

    Алексей Шарапов: Я согласен с тем, что это будет боль. Но самое главное — не создавать SOA в этом случае. Это же не микросервис: протаскиваешь через распределенные данные монолита из кусков какое-то значение, которое ты должен везде обработать. Почему твое значение не может быть отдельным микросервисом, из которого все берут данные? Или который это обрабатывает отдельно от всех, чтобы не нарушать состояние остального. Если такие требования появились, как их вписать со стороны идеологии? А если это вам не подходит, зачем вы вообще начали делать микросервисы?

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

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

    Больше по этому поводу мне нечего сказать. Наверное, это вопрос ко все участникам разработки.

    Андрей Булов:  О, я тебя заразил здравым смыслом! 

    Тестирование. 

    Мой любимый вопрос на Lead Test Engineer или Test Manager. Я рисую такую картинку и говорю:

    — Это система, которая работает с деньгами — пусть будет продажа машин. Если мы там что-то потеряем, человек не получит машину, а компания не получит деньги, плюс ее ждут репутационные издержки и т.д. Вопрос: как нам релизиться раз в спринт, не падать в проде и не попасть на штрафы? Напиши мне такой процесс тестирования, и я смогу убедить разработчиков написать тест. Но только напиши мне так, чтобы я был уверен хотя бы на 85%, что я в проде не упаду.

    На этот вопрос, к сожалению, пока мало, кто ответил. Все почему-то говорят про модульные тесты, про то, что нам нужно окружение, еще одно окружение, еще одно окружение. 

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

    Ни технически, ни организационно идеальных практик пока, к сожалению, нет. В общем, тяжело это работает. С монолитом проще: взяли Selenium, все протестировалось, смоками покрыли, выкатываемся в прод — все работает. Мы красавцы, мы восхитительны!

    Алексей Шарапов: А как же без проблем, Андрей? Может быть, в том, что касается тестирования, я с тобой согласен. Я не то чтобы заразился здравым смыслом. Просто не так глубоко погружался в проблемы тестирования. 

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

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

    Не надо тащить за собой опыт монолита, применять его на микросервисах и говорить — блин, ничего не работает, как нам теперь жить, и что же с этим делать? 

    Частично, Андрей, я с тобой согласен, но и монолит не отменяет множества стендов. Я не могу себе представить отчаянных людей, которые запустили монолит на одной машине, чтобы сэкономить свои ресурсы, и сказали: «Все классно! Мы никогда не падали, а во время деплоя там огромный downtime».

    Андрей Булов:  Уел!

    Хочу рассказать про «каждому разработчику по своему Куберу». CI/CD — моя любимая тема.

    Во-первых, чтобы это все собрать, нам нужен очень хороший Jenkins с кучей слейвов. В разработке возникает несколько вопросов:

    • Мы пересобираем все сервисы каждый коммит?

    • Сколько нужно слейвов на сборку?

    Приходит бизнес и говорит:

    — А сколько нам нужно заплатить за сборку? Сколько-сколько? Нет, вон там стоит под столом сервер, давайте его использовать.

    • А почему все так медленно работает?

    — У меня пять разработчиков сделали коммиты, и пять раз подряд пересобирается весь этот зоопарк.

    Помимо очень мощного окружения нужен очень мощный CI/CD. 

    • Можем ли мы считать, что у нас работает система, когда собралось 60 микросервисов, и 61, который мы не релизим, упал? 

    —  У меня вопрос: можем мы зарелизиться, или нет? 

    — Тот сервис, конечно, релизить не будем, остальные зарелизим. Какая радость от того, что мы в проде упадем? 

    — А нужно ли вообще смотреть, что с этим микросервисом? Мы его уже 100 лет не трогали, что-то упало.

    — Ну, не знаю. Может быть, сам заработает.

    С continuous delivery отдельная песня, когда нам нужно заделиверить что-то. Мы деливерим, деливерим, деливерим это в прод — бах! — падает какая-нибудь джоба, нам это нужно пересобирать все по новой, и т.д. В общем, это гораздо больнее, чем собрать один Maven clean install, прогнать все тесты —  все работает, мы великолепны.

    Алексей Шарапов: А как жить без CI/CD? Попробую описать, что я имею в виду.

    Мне кажется, что CI и CD необходимы для любого проекта. Ты используешь CI в проекте с монолитом, с микросервисами. Почему появляется необходимость на каждый коммит пересобирать все-все-все микросервисы? Здесь стоит опять задуматься о независимости. Возможно, разговор тут идет не про инструменты. Однако, предположим, какой-нибудь GitLab CI с его Docker runners сильно сэкономили бы тебе ресурсы. Мы не говорим про этот страшный Jenkins, который перегружен, огромную Java-машину. Мы можем использовать что-то более легковесное. 

    Может быть, каждый CI/CD должен заканчиваться на том моменте, где это на самом деле необходимо. Если речь идет об огромном монолите, который работает в нашем энтерпрайзе, скажу честно, CD у нас поскольку постольку, просто потому что есть такие условия. Однако же мы предоставляем и такой инструмент. И мы не берем jenkins , как мы привыкли, а находим необходимый инструмент — легковесный, удобный. Именно с его помощью мы что-то делаем, и это классно работает. 

    Я просто не могу себе представить, как можно жить  без CI/CD. У нас микросервисы — это огромный проект, все они собирались отдельно. Был микросервис, который жил с самой первой версии, никогда не менялся, мы его не пересобирали, однако же он всегда работал. Вот она — независимость.

    Андрей Булов:   О, вот это мой любимый вопрос на собеседовании — отдельные DevOps команды.

    Допустим, у нас есть вполне себе микросервисный ландшафт с базами под каждый микросервис. Все это в consistency состоянии находится, все прямо по матчасти. Приходит заказчик и говорит: «Пожалуйста, перед выкаткой сделайте бэкап прода. И сделайте нормально, чтобы транзакции загасились, мы все забэкапили, сохранили и дальше накатывали, потому что деньги, заказы — страшно».

    Мой любимый вопрос DevOps’ам: как написать такую чудесную синюю кнопку, которую жмешь, все базы в один момент с каким-то снепшотом бэкапятся. А еще все это можно потом либо восстановить одной зеленой кнопкой, либо слить разработчикам на дев-окружение. Причем мне нужно не ощущение: «Ну, в принципе, нормально! Вроде, все закончилось», а что-то более доказательное. Если бизнес говорит: «Ребята, это какая-то фигня», что мы ему можем возразить в ответ? Что, по нашим ощущениям, все должно работать?

    Как останавливать кучу баз в один момент в микросервисах — это хороший вопрос. Сможешь ли ты на него ответить?

    Алексей Шарапов: Нет, потому что это один из самых сложных вопросов касательно микросервисов.

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

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

    То есть нужно постараться максимально избегать ситуации, когда все это придется в огне восстанавливать, и это уже решит часть твоих проблем. Я обычно делаю ставку именно на это. Но, на самом деле, подходов много. Когда приходишь, а тебе говорят: «Мы сделали одну базу, она крутится, все к ней обращаются. А у нас микросервисы, что теперь делать?», бывает страшно. Об это можно открыть отдельную дискуссию.

    Андрей Булов:  

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

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

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

    Алексей Шарапов: Абсолютно согласен — не нужно применять микросервисы там, где этого не требуется. Я хочу привести пример того, как я это представляю. Мы не можем запустить  проект в продакшен, пока не будет написано большое количество бизнес-логики. Но мы можем посмотреть на это с другой стороны: у нас есть простой бизнес. Предположим, я сейчас делаю автоматическое создание ресурсов внутри нашей сети. 

    Крошечный скейтбордик — это первый маленький микросервис, который дергает по REST какой-нибудь AWX и запускает создание первой машины: класс, продукт уже есть, и я могу пользоваться этим каждый день. Потом я хочу сделать самокат. Прикручиваю туда базу данных, чтобы ходить в стейты. Дальше велосипед, мотоцикл, в конце машина — это уже AWX плюс Terraform, Cloud, которые взаимодействуют между собой через разные микросервисы, Kafka. Я могу создавать какие-то вещи уже с первой улыбающейся рожицы, которая на меня смотрит (LIKE THIS).

    Или возьмем другой бизнес-кейс. Предположим, у вас магазин с напитками. Сегодня вы принимаете заказ с одним напитком, но когда у вас есть автомобиль, это уже огромная сеть ресторанов. 

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

    Профессиональная конференция по интеграции процессов разработки, тестирования и эксплуатации DevOpsConf 2021 пройдет 30 и 31 мая 2021. Но билеты на нее вы можете приобрести уже сейчас, успев сделать это до повышения цены.

    А еще вы можете сами стать героями конференции, подав доклад.

    Хотите бесплатно получить материалы предыдущей конференции по DevOps? Подписывайтесь на рассылку.

    Конференции Олега Бунина (Онтико)
    Конференции Олега Бунина

    Похожие публикации

    Комментарии 30

      0
      микросервисы VS монолит
      — когда я слышу такую постановку вопроса, всегда хочется задать участникам дискуссии вопрос: а про SOA вы что то слышали? К чему это полярное мышление окрашивающее все в два цвета — черный и белый? Вся дискуссия сводится к тому что то что для одного черное, для другого белое и никто не говорит о масштабах задачи. У одного в голове условный Twitter (хотя систем такого масштаба не так уж и много), у другого в голове условная офисная CRM
        0
        Про SOA есть внутри, я про это тоже упоминал, а именно в формате батла было специально выбрано 2 разных подхода, просто чтобы не уходить в дебри архитектурных подходов.
        0
        статья интересная, спасибо.

        итого получается
        1) административная неповоротливость, множество команд
        2) сложно и медленно разрабатывать когда система вне стадии MVP
        3) сложно тестировать и убедиться в надёжности
        4) сложно дебажить
          0
          Монолит на java, это идеальный монолит. Обычно на практике монолит реализован на OEBS, Siebel, ЦФТ, Colvir, etc. И если там, к примеру пилит 5+ команд, с отладкой и тестированием все грустно. С развертыванием отдельных контуров — еще грустнее.

          В целом, серебряных пуль не бывает, и с монолитом, и с микросервисами нужно вдумчиво работать.
            0
            Абсолютно согласен, необходимо подбирать подход под проект, а не наоборот
            +1
            Микросервисы — это в первую очередь масштабирование процесса разработки.
            • НЛО прилетело и опубликовало эту надпись здесь
                0
                Всегда удивлял этот аргумент. Серьезно, вы готовы пожертвовать (а в большинстве случаев микросервисы — это «жертва») архитектурой системы ради процессов разработки?


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

                открыл рандомную популярную книгу про микросервисы, Monolith to microservices, Sam Newman
                samnewman.io/books/monolith-to-microservices

                похоже эти все проблемы известны уже давно

                Chapter 5: Growing Pains
                More Services, More Pain
                Breaking Changes
                Reporting
                Monitoring and Troubleshooting
                Local Developer Experience
                Running Too Many Things
                End-to-end Testing
                Global Verses Local Optimization
                Robustness and Resiliency
                Orphaned Services


                мне так видится что отрасль постепенно делает своего рода Тик-так (как у Интела): сначала вводит какое-то новшество чтобы решать проблемы, потом фиксит проблемы которые дало это новшество…
                Так было например с NoSQL и озерами данных. Было время когда все повально кинулись туда, наклепали NoSQL, баз на хадупе и тд, а потом маятник качнулся в другую сторону, и сам же Google, который был пионером big data, сделал Spanner и мотивом было «лучше транзакции и ACID будут с задержками в распределенной субд чем если снова и снова писать велосипеды для транзакций поверх NoSQL» (не дословно, можно открыть и почитать их white paper). Вот эти проблемы — непонятная надежность, дебаг, тестирование, должны привести к тому что либо будут найдены решения (service mesh?) либо маятник снова качнется в другую сторону, когда поймут что проблемы микросервисов достаточно серьёзные.

                  0
                  Жертвуешь ты архитектурой системы или нет — зависит от того, как проложены границы микросервисов.
                  Если на каждое второе действие вы синхронно запрашиваете все свои микросервисы (а иногда еще и по кругу А -> B -> C -> A ->D -> B -> A), то, вероятно, границы проложены неверно.
                  В прилично же раскроенных микросервисах разработка намного проще и быстрей
                    0
                    Не бывает прилично раскроенных микросервисов, бывают простые бизнес-задачи.
                    Но в таких случаях, когда границы контекста ясны, никто не мешает сделать и 2 отдельных монолита.
                    В реальном большом бизнесе границы настолько размыты, что выделять контексты архитектор будет первые полгода. А потом после пары месяцев разработки, пойдет переделывать потому что на самом деле все не так.

                      0
                      Ну это и печально, когда бизнес не хочет или не может объяснить как он работает — архитектору приходится придумывать свои схемы. Натягивание совы на глобус никогда не бывает гладким.
                +1
                В прилично же раскроенных микросервисах разработка намного проще и быстрей


                за счет чего? Допустим мне чтобы вмёржить 100 строк кода, надо пройти ревью в трёх репозиториях. Быстрее разрабатывать отдельный микросервис который ни от чего не зависит, но интегрироваться намного медленнее.
                  +1
                  Если вам нужно мерджить в 3 репозитория, то скорей всего у вас таки проблемы с границами.
                  Обычно вы работаете с одним сервисом и до тех пор, пока не рушите его АПИ, вы ничем не ограничены.
                  0
                  Если вам нужно мерджить в 3 репозитория, то скорей всего у вас таки проблемы с границами.
                  Обычно вы работаете с одним сервисом и до тех пор, пока не рушите его АПИ, вы ничем не ограничены.


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


                    это всё понятно. Я говорю с точки зрения девелопера, и какие у этого есть проблемы. Например есть проблемы когда нужно интегрироваться, а если нужно сделать вещь которая затрагивает 10 микросервисов, то нужно общаться с 10ю командами, делать пулл реквесты или вынуждать это делать эти команды. Это не так просто.

                    Начинать с микросервисов (особенно если вы только ищете свой продукт и не ясно что в итоге получится) такая себе затея.


                    микросервисы могут активно меняться и интегрироваться с другими не только во время распилов монолита или переходов. Мне кажется вы рассуждаете «паттернами идеального мира» где всё происходит прям как в какой-то книге написано.
                      0
                      Если у вас задача, которая требует изменения в 10 сервисах, то в случае монолита это будет точно такое-же большое изменение, обсудить которое вам придется все с теми же людьми с теми же проблемами. Но большинство задач не такие, в большинстве случаев вы будете работать только с одним сервисом, который по сравнению с монолитом гораздо меньше (проще держать в голове контекст происходящего и возможные последствия изменений).

                      По поводу изменений в сервисах, да может быть такое, что нужно что-то менять. Но снова, не нужно добавлять в сервис новые обязанности, только потому, что на первый взгляд не понятно кто должен эту новою работу выполнять. Придерживайтесь того же SRP, Low coupling/High cohesion как и при написании кода, делайте сервисы слабо связанными и сфокусированными на одной бизнес-задаче и не создавайте себе дополнительных сложностей.

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

                        Вот эту самую интеграцию и надо выпиливать в обоих случаях. Нет большой разницы, выпиливать вызов service->method() или httpClient->request('GET', 'service/method').

                          0
                          В больших командах разница есть. В теории никто не мешает писать монолит так, чтоб модули пересекались по минимуму, но на практике чем больше проект и больше команда — тем чаще срезаются углы, растет coupling и вот это вот все. Сервисы же физически разграничены. Косячить тоже можно, но это трудней
                            0
                            По поводу изменений в сервисах, да может быть такое, что нужно что-то менять. Но снова, не нужно добавлять в сервис новые обязанности, только потому, что на первый взгляд не понятно кто должен эту новою работу выполнять. Придерживайтесь того же SRP, Low coupling/High cohesion как и при написании кода, делайте сервисы слабо связанными и сфокусированными на одной бизнес-задаче и не создавайте себе дополнительных сложностей.


                            открыл на днях Фаулера, его статью о микросервисах. В разделе «Микросервисы это будущее?» он пишет что пока рано говорить, т.к. сейчас недостаточно данных судить об успешной адаптации кроме тех. гигантов.
                            то что вы говорите, конечно верно, но проблемы отладки (более широко — удобства разработки), тестирования и особенно простоты интеграции остаются и пока что видятся фундаментальными ограничениями технологии как таковой, которые возможно нельзя обойти в принципе. Вот эти вещи «SRP, Low coupling/High cohesion» скорее облегчают жизнь, но интеграция и масштабный девопс никуда не деваются, потому что микросервисы это распределённая система со всеми вытекающими сложностями
                              0
                              Микро-сервисы намного проще разрабатывать чем монолит, как раз за счет сильно ограниченного контекста. Сервисы проще и меньше. Да, более сложный мониторинг и легче отстрелить себе ногу, если не думать что делаешь.
                              А так Jaeger \ DataDog вполне позволяют легко отлаживать систему в сборе. Отдельные же сервисы отлаживаются точно так-же как и монолитные приложения.
                                0
                                Микро-сервисы намного проще разрабатывать чем монолит, как раз за счет сильно ограниченного контекста.


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

                                А так Jaeger \ DataDog вполне позволяют легко отлаживать систему в сборе


                                это разве отладка? Дистрибютед трейсинг это разве тоже самое как если бы я поставил точку останова в приложении?

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


                                чтобы запустить локально, нужно воссоздать на локальной машине не только сам сервис но и другие сервиса с которым этот микросервис общается. А ещё это могут быть AWS ресурсы, не на все из которых есть докер аналоги. И даже если это возможно, это куда более накладно. Ничего себе «точно так же» ))
                                  0
                                  отдельный микросервис проще разрабатывать чем монолит, а всю систему — сложнее.

                                  это разве отладка? Дистрибютед трейсинг это разве тоже самое как если бы я поставил точку останова в приложении?

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

                                  чтобы запустить локально, нужно воссоздать на локальной машине не только сам сервис но и другие сервиса с которым этот микросервис общается. А ещё это могут быть AWS ресурсы, не на все из которых есть докер аналоги. И даже если это возможно, это куда более накладно. Ничего себе «точно так же» ))

                                  Не завязывайтесь на 3rd-party напрямую и не будет проблем. В крайнем случае вы сможете напилить свой адаптер для локальной работы, если вендор не предоставляет такой возможности.
                                  Ну и вовсе не обязательно поднимать локально все сервисы, общепринятая практика поднимать контейнер только с одним сервисом, а все остально брать с dev окружения.
                                    0
                                    Если ваши сервисы хорошо изолированы, то чаще всего вы и работать будете с одним. И поставить точку останова вы сможете. К сожалению очень часто путают (микро-)сервисную архитектуру и распределенный монолит. А трейсинг как раз поможет понять в каком из сервисов искать проблему.


                                    и что покажет трейсинг? что какой-то сервис в цепочке вернул 500-ку или 400-ку? А если они вернули 200 но результат неправильный? Трейсинг это же не дебаг ) А в логах могут не печататься респонзы ) А причина неправильно посчитанного значения может быть как в одном сервисе так и в нескольких и даже в их взаимодействии. И чтобы это понять, нужно реально продебажить. Ну или добавлять логи в несколько сервисов и деплоить и смотреть )
                                    Вы упорно делаете вид будто бы отладка системы из кучи компонентов и связей между ними это тоже самое что и отладка одного приложения. Так это же просто неправда, и что мы тут обсуждаем вообще?

                                      0
                                      Вы можете дебажить и несколько сервисов. Это менее удобно конечно, но эта возможность есть.
                                      Из своего опыта скажу, что такой необходимости у меня не возникало, обычно все ограничивается одним сервисом
                      0
                      Вариант — половина кода в монолите, половина — в микросервисах не рассматривается? В любом проекте полно кода, которые так и просятся в микросервис
                        0
                        ИМХО, это наиболее вероятный исход. С монолита по чуть-чуть выпиливают независимые части, когда становятся ясными их границы
                          0
                          МикроХипстота Индустрия до такого еще не доросла ;)
                          0
                          Недавно общался с человеком (на собеседовании), который сказал, что они пытаются перейти на микросервисы потому что джанго орм не справляется с их сложными запросами. Не вдаваясь в дебри (а тут возникает очень много вопросов) выяснилось, что ребята не знали про то какие существуют эффективные способы хранения деревьев в базе данных. В итоге они думали, что именно микросервисы им помогут справиться с нагрузкой.
                            0
                            чем больше людей тем хуже показывают себя монолиты в частности при мерже наступает локальный ад

                            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                            Самое читаемое