Как стать автором
Обновить

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

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

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


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

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

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

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

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

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

Бизнес логика имеет примерно одинаковый объем при любом раскладе и может уменьшится только переходом на более абстрактный DSL.

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

НЛО прилетело и опубликовало эту надпись здесь

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

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

НЛО прилетело и опубликовало эту надпись здесь

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

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

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

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

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

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

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

Пользовательский сервис это не микросервис

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

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

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

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

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

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

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

  • SDET и QA Automation.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Упс, перепутал микросервисы с обычными сервисами.

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

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

С чего это? Монолит также может быть горизонтально отмасштабирован с load balancer-ом и high availability.

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

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

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

Зато весь процесс тестировать становится на порядки сложнее.

Так где плюсы-то?

С чего это?

Ну как минимум в монолите Graceful degradation не получится реализовать, если он ложится целиком, или если забивается какой-то канал связи с внешним сервисом, не делящийся справедливо между разными модулями (условно пул коннектов).

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

Все еще аргумент про Graceful degradation в случае, если падает монолит целиком (например, из-за низкой нагрузки отмаштабировались в 2 воркера, а потом у вас упали 2 "железных" ноды в кластере по какой-либо причине). А монолит может влечь за собой долгие рестарты при достаточно большом количестве кода и/или достаточно большом количестве, например, непрогретых кешей

+ раздельное маштабирование (маштабируем отдельно условный сервис обслуживающий чаты в какой-то платформе, а отдельно - процессинг заказов в той же платформе). И заодно отпадает проблема с тем, что перегруз 1 из модулей напрягает рантайм так, что времени обработать нормально запросы других модулей не хватает. Да, можно маштабировать весь монолит целиком, но во первых, есть низконагруженные, но тяжело маштабирующиеся задачи, а во вторых, это оверхед от лишнего дублирования всевозможных кешей и стейтов в низконагруженной части (а кеши бывают весьма жирные)

+ возможность писать разные сервисы разными командами, на разных стеках

+ возможность делать большие обновления зависимостей поэтапно, без конфликтов

+ возможность быстро готовить пачки изменений, затрагивающие небольшую часть кодовой базы (хотфиксы, etc)

Все еще аргумент про Graceful degradation в случае, если падает монолит целиком

Не совсем понял, что такое "падает монолит целиком". Для Graceful degradation существуют всеразличные пулы ресурсов, и очереди с лимитированной глубиной. Если свободного ресурса нет, то вместо ожидания сразу отфутболить реквест, тем самым предотвращая каскадное истечение ресурсов.

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

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

возможность писать разные сервисы разными командами, на разных стеках

Принимается, хотя со стратегической точки зрения это скорей не плюс, а минус.

возможность делать большие обновления зависимостей поэтапно, без конфликтов

Большие обновления зависимостей в микросервисной архитектуре -- это боль. Особенно когда малейшее изменение затрагивает сразу много микросервисов (а таких бывает большинство).

возможность делать большие обновления зависимостей поэтапно, без конфликтов

Это да. Принимается.

Вобщем, все "плюсы" и "минусы" разложены хрестоматийно и как обычно без всякой критики. В монолите имплементируется любой паттерн из микросервисной архитектуры, и делается это все порядки проще подручными средствами, а любые ресурсы могут быть точно также изолированы для каждого компонента. Кроме двух: CPU и memory. Вот тут и находится главный мотив по которому стоит переходить на микросервисную архитектуру. Железные инстансы теперь являются такими же ресурсами, как и любые пулы, а микросервисная архитектура позволяет осуществлять динамическое выделение инстансов под компоненты, изолируя при этом использование CPU и памяти. Цена перехода -- усложнение инфры, бизнес логики, процессов и общей стоимости.

Монолит также может быть горизонтально отмасштабирован с load balancer-ом и high availability.

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

Вторая проблема это неравномерное масштабирование. В больших комплексах часто надо масштабировать конкретную функцию, а не весь объем кода. Размножать весь монолит, ради одной функции нелепо. И тут мы приходим к давней идее аппликейшен серверов, RPC, DI, resource pooling и прочего. Называется по-другому, но в общем-то это тоже микросервисы и контейнеры, только без k8s и https everywhere.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий