Иллюстрация @alvaro_sanchez
Некоторое время все сходили с ума по микросервисам. Невозможно было открыть любимый новостной агрегатор и не увидеть, чтобы какая-то неизвестная вам доселе компания рассказывает о спасении своего инженерного отдела с помощью микросервисов. Возможно, вы даже сами работали в компании, которую захватил ажиотаж крохотных, магических маленьких сервисов, которые решат все проблемы большой, запущенной, полной легаси кодовой базы.
Естественно, в реальности все оказалось совсем наоборот. Когда смотришь назад, на произошедшее, то зрение оказывается ближе к 100%, чем когда смотришь с надеждой в будущее.
Я хочу рассказать о некоторых важных заблуждениях и подводных камнях движения за микросервисы с точки зрения человека, который работал в компании, убежденной в идее целительных свойств микросервисов. Я не хочу, чтобы выводом этой статьи для вас стало "микросервисы == плохо", но в идеале я хотел бы, чтобы вы задумались о проблемах когда будете решать, подходит ли вам микросервисная архитектура.
Что такое "микросервис" вообще?
Не существует идеального определения, но люди, которые продвигают эту область смогли описать неплохой набор требований к системе, по которым её можно было бы отнести к "микросервисной" архитектуре.
Можно сказать, это — не монолит. На практике это означает, что микросервис работает лишь с небольшой, максимально ограниченной областью задач. Он выполняет минимум функций для достижения определенной цели в вашем стеке. Вот более конкретный пример: допустим, в банке есть "Login Service", и вы, конечно, не хотите, чтобы у этого сервиса был доступ к финансовым транзакциям ваших клиентов. Эту область вы вынесете в какой-нибудь “Transaction Service” (имейте ввиду — давать названия очень сложно).
В дополнение, люди часто подразумевают, что микросервисы должны общаться с другими сервисами удаленно. Так как они являются самостоятельными процессами, и часто запущены далеко от других, обычно такие процессы общаются друг с другом по сети используя REST или какой-нибудь другой протокол RPC.
Пока все кажется достаточно простым — нужно просто обернуть небольшие куски системы в какой-нибудь REST API, и пусть все общаются друг с другом по сети. По моему опыту, есть 5 "истин", в которые верят люди, и которые не всегда бывают истинными:
- Код будет чище
- Писать модули, решающие одну задачу — легче
- Это работает быстрее, чем монолит
- Инженерам проще, если не нужно работать с единой кодовой базой
- Это самый простой способ обеспечить автоматическое масштабирование, и тут где-то замешан Докер
Заблуждение #1: Более чистый код
«Не нужно добавлять сетевое ограничение чтобы оправдать написание лучшего кода».
Правда жизни в том, что ни микросервисы, ни любой другой подход при моделировании технического стека не являются требованием для написания более чистого и поддерживаемого кода. Конечно, раз движимых частей меньше, то снижается возможность писать ленивый и непродуманный код. Но это как говорить, что кражи можно победить убрав товары с витрин магазинов. Вы не решили проблему, вы просто удалили много возможностей.
Популярный подход — строить архитектуру таким образом, что логические "сервисы" владеют частями предметной области. Это похоже на концепцию микросервисов, потому что зависимости, управляющие системой, будут явными. И бизнес-логика не будет влезать в разные углы. К тому же, такой подход не навлекает на себя чрезмерное использование сети и возможные проблемы, связанные с этим.
Еще одно преимущество этого подхода в том, что оно напоминает сервис-ориентированную архитектуру (Service Oriented Architecture), построенную на базе микросервисов: если вы решите перейти к микросервисам, то большая часть работы уже выполнена, и у вас скорее всего уже есть неплохое понимание предметной области для правильного разделения ее частей. Настоящий SOA начинается с кода, и с течением времени продолжается на уровне физической топологии стека.
Заблуждение #2: Это легче
«Распределенные транзакции никогда не легче»
Снаружи может казаться иначе, но большинство предметных областей (особенно в новых компаниях, которым нужно создавать прототипы, делать пивоты и в целом переопределять саму область много раз) невозможно разделить на аккуратные, четкие коробочки. Зачастую произвольной части системы требуется получить данные о другой части чтобы работать корректно. Все усложняется еще сильнее, когда она делегирует операцию записи данных другой части, за пределами своей предметной области. Когда вы вышли за пределы своей зоны влияния, и вам нужно задействовать другие части для хранения или изменения данных, то вы попали в страну распределенных транзакций.
Когда в рамках одного запроса задействовано несколько удаленных сервисов, сложность сильно возрастает. Можно ли обращаться к ним параллельно или нужно обращаться последовательно? Известны ли вам все возможные ошибки заранее (на уровне приложения и на уровне сети), которые могут возникнуть в любой момент, на любом участке цепи, и что эти ошибки будут означать для самого запроса? Зачастую, каждой из распределенных транзакций требуется свой подход к обработке ошибок. И понять все ошибки и понять, как их решать — это очень, очень большая работа.
Заблуждение #3: Это быстрее
«Можно сильно улучшить производительность монолита если добавить немного дисциплины»
Это заблуждение сложно опровергнуть, потому что в реальности мы часто можем ускорить отдельную систему, если уменьшим количество задач или количество загружаемых зависимостей, и так далее.
Но в целом, это не системное доказательство. Я не сомневаюсь, что если вы перешли на микросервисы, то изолированный в этих сервисах код мог ускориться, но не нужно забывать про появившиеся задержки из-за сетевых запросов. Сеть никогда не бывает такой же быстрой, как внутренняя коммуникация, то иногда бывает «достаточно быстрой».
К тому же, многие истории об увеличении производительности на самом деле связаны с преимуществами нового языка или целого технологического стека, а не просто архитектурой микросервисов. Если переписать старое Ruby on Rails, Django или NodeJS приложение на новом языке вроде Scala и Go (два популярных выбора для микросервисной архитектуры), то производительность улучшится хотя бы из-за улучшений производительности новых технологий в целом. Но этим языкам вообще-то без разницы, если вы будете называть их процессы "микро". Они работают быстрее ввиду простых факторов вроде компиляции.
Также, в большинстве приложений в стартапах чистая производительность процессора и памяти почти никогда не является проблемой. Обычно проблема в I/O, а дополнительные сетевые вызовы только увеличивают I/O.
Заблуждение #4: Лучше для инженеров
Когда много инженеров работают в изолированных кодовых базах, то возникает синдром «это не моя проблема».
Может показаться, что когда маленькие команды работают над маленькими частями головоломки, то все будет проще. Но в итоге такая конфигурация может привести к проблемам.
Самая большая проблема в необходимости запускать постоянно растущее количество сервисов для любого, даже самого маленького изменения. То есть нужно вложить время и усилия чтобы построить и поддерживать систему, где каждый инженер может запускать все локально. Такие штуки, как Докер могут упростить этот момент, но кому-то все же придется поддерживать конфигурацию на протяжении жизни проекта.
К тому же, это усложняет написание тестов. Чтобы написать нормальный набор интеграционных тестов, нужно понимать все сервисы, связанные с конкретной операцией, принять во внимание все возможные ошибки и так далее. На понимание системы будет уходить больше времени, чем на разработку системы. И хотя я никогда не скажу инженеру, что понимать систему — это трата времени, я все же хочу предостеречь его от преждевременного добавления сложности.
И, наконец, такая конфигурация создает социальные проблемы. Баги могут жить одновременно в нескольких сервисах и требовать изменений на уровне нескольких команд. Им нужно синхронизироваться и координировать усилия. К тому же, люди могут терять чувство ответственности и стараться спихнуть как можно больше проблем другой команде. Когда инженеры работают вместе, над одной кодовой базой, то понимание системы растет одновременно с пониманием друг друга. Они с большей вероятностью будут работать над решением проблем вместе, вместо того, чтобы быть королями и королевами маленьких изолированных княжеств.
Заблуждение #5: Лучше масштабируется
«Микросервис можно масштабировать вширь также, как и монолит»
Упаковать сервисы в отдельные юниты и масштабировать их с помощью, скажем, Докера — это хороший подход для горизонтального масштабирования, без сомнений.
Однако, это можно сделать не только с микросервисами. Подход работает и в случае с монолитными приложениями. Можно сделать логические кластеры монолита, которые обрабатывают части трафика. Например, входящие API-запросы, фронтэнд панели управления и фоновые задачи могут находиться в одной кодовой базе, но не обязательно на каждой машине обрабатывать все три типа запросов.
Преимущество здесь такое же, как в случае с микросервисами: отдельные кластеры можно настраивать в зависимости от нагрузки, а также масштабировать их по отдельности, реагируя на скачки трафика. Микросервисная архитектура с самого начала толкает к такому подходу, но ничего не мешает вам применить такой же метод для масштабирования монолитного стека.
Когда использовать микросервисы
«Когда вы, как инженерная организация, будете готовы»
Я хочу закончить эту статью обсуждением того, когда же наступит правильное время перейти к микросервисам (или, если вы уже начали, как понять, было ли это правильным моментом).
Самая главная вещь на пути к хорошей, работающей микросервисной архитектуре — это простое понимание своей предметной области. Если вы не понимаете ее, или все еще пытаетесь понять, то микросервисы принесут больше проблем, чем решений. Но если у вас уже есть глубокое понимание, то вам знакомы границы и зависимости, и микросервисный подходом может быть правильным шагом.
Еще один важный момент это ваше рабочее окружение, особенно, как оно будет выглядеть в контексте распределенных транзакций. Если вам знакомы пути каждой категории запросов в системе, и вы понимаете где, как и зачем эти пути могут сломаться, тогда вы сможете построить распределенную модель для обработки запросов.
Кроме понимания окружения есть тема мониторинга окружения. Она выходит за пределы дискуссии "микросервис vs. монолит", но мониторинг должен быть в основе инженерных усилий. Вам скорее всего понадобится много информации о разных частях системы чтобы понять, почему одна из частей ведет себя плохо или даже генерирует ошибки. Если у вас налаженная система мониторинга составных частей системы, тогда вы сможете понимать поведение системы при горизонтальном масштабировании.
И, наконец, если вы на самом деле продемонстрируете пользу своей инженерной организации и бизнесу в целом, тогда движение к микросервисам поможет расти, масштабироваться и зарабатывать деньги. Конечно, строить интересные системы и пробовать новые штуки — это круто, но в итоге у любой компании есть самый важный показатель. Если приходится откладывать релиз новой фичи, которая принесет компании деньги, из-за поста в каком-то блоге про "монолиты это плохо", то придется оправдывать это решение. Иногда это того стоит. Иногда — нет. Знать, когда нужно настоять и уделить время поможет вашей репутации в долгосрочной перспективе.
Выводы
Надеюсь, теперь у вас появился набор условий и вопросов, которые нужно разрешить если кто-то предложит микросервисный подход. Как я говорил в начале, моей целью не было доказать, что "микросервисы это плохо". Но спрыгивать на микросервисы не подумав обо всех возможностях деталях и вопросах — это напрашиваться на проблемы в будущем.
Если спрашивать моего совета, то я бы смотрел в сторону "внутренних" сервисов на основе чистых, хорошо определенных модулей в коде. Их уже можно будет вынести в настоящие сервисы в будущем, если появится такая необходимость. Этот подход — не единственный возможный, и уж точно не панацея от плохого кода. Но он поможет вам продвигаться вперед быстрее, чем если вы закопаетесь в микросервисы раньше нужного.
Комментарии (99)
Ogoun
28.09.2016 13:37+10А ведь достаточно не зацикливаться на одном паттерне (на любом масштабе), а каждый раз думать что подойдет в конкретной ситуации. Зачастую самыми надежными оказываются гибридные решения. Монолит+микросервисы, наследование+композиция и т.д… Микросервисы вовсе не плохи во многих случаях, например, если хочется построить пайплайн для обработки потока данных, при этом по большей части обработчики не зависят друг от друга, то нет смысла делать их модулями в одном процессе, гораздо надежнее разнести на отдельные сервисы, каждый из которых можно независимо обновить/отключить.
quwy
29.09.2016 08:48+6Проблема в том, что современная IT-индустрия поражена инфантилизмом и максимализмом. Каждый год ее несет в направлении очереденого супер-пупер-иновационного подхода, который ну вот теперь наврняка решит все проблемы. Позачера они молились на виртуализацию, вчера на облака, сегодня на микросервисы, завтра еще какую-нибудь фигню придумают. Вместо того, чтобы коров лечить, они заборы красят.
Gugic
29.09.2016 12:06Ну в общем-то в итоге большие ребята так и сидят на виртуальных серверах в облаках, и потихоньку дробятся на микросервисы, которые распихиваются по контейнерам. И это нормальный абсолютно подход к проектированию сейчас.
quwy
29.09.2016 12:38Угу, вот только качество сервисов от этого лучше не становится почему-то.
Renius
04.10.2016 12:22Как вы считаете общее качество сервисов?
quwy
04.10.2016 12:56По удобству (и принципиальной возможности) их использовать. Например, не далее, как позавчера не смог в чужом городе воспользоваться одним из картографических сервисов на смартфоне. Карта не хотела ни скроллиться, ни масштабироваться. Она просто игнорировала соответствующие жесты. При этом оболочка страницы все это выполняла как полагается.
Каждый год я слышу об очередном чертовом «инновационном прорыве», но такие случаи не только не становятся реже, их частота стремительно растет. А все потому, что не «прорывы» нужно совершать, а нормально писать и тестировать. Тогда все будет просто работать.
VolCh
05.10.2016 12:54+1Есть мнение, что без «супер-пупер-иновационных подходов» качество и/или функциональность сервисов было бы ниже. Грубо говоря, без них или функциональность была бы сейчас на уровне прошлого века, или качество бы было ещё ниже. Ну или и то, и другое. По сути все эти подходы — средство борьбы со сложностью, а сложность сервисов/продуктов постоянно возрастает.
lesha_firs
28.09.2016 13:44+13На мой взгляд одним из важным достоинством микросервисов, это то что мы не привязываемся к одному языку программирования, что дает больше гибкости.
Мы можем переписать 1 сервис на другой язык, ну к примеру на java и протестировать как это будет работать. мы даже можем протестировать это на процентном соотношение, например «Сервис комментарий у нас на python, мы переписали его на java и пустили трафик 70/30» и померили что быстрей…
Такое невозможно сделать с монолитом.sentyaev
28.09.2016 17:03+3Написать микросервис (или просто сервис) проблем нет, я думаю всетаки основной вопрос как выделять эти микросервисы и когда.
А то бывает смотришь, а в проекте есть микросервис который называется CORE. Ну вы поняли)
Я к тому, что рассуждать на тему нужны микросервисы или нет странно, у меня в проектах и 10 лет назад были микросервисы (просто мы их так не называли).VolCh
28.09.2016 21:42Ну вот у меня есть core. То, что осталось от монолита, по сути аутентификация и авторизация, неразрывно с ними связанное логирование и разные справочники, крайне редко изменяемые.
yara_73
30.09.2016 00:01А можно поподробнее о микросервисе Core, чем вам он не угодил, и что по вашему нужно было исправить?
sentyaev
30.09.2016 00:16+1Это я имел ввиду нечто, не имеющее специализации. Из моей практики, под словами Core обычно понимают что-то вроде единой точки доступа к бэкенду (может называться core-api).
Есть и другие варианты — Shared, Common, Public, Internal и т.д. Это может иметь еще префиксы или суффиксы такие как Data, Api, Service и т.д.
А проблема в том, что эти названия не имеют никакого отношения к предметной области, да и к функциональности.
Конечно же, если в вашей предметной области слово Core имеет смысл (как например Order или Shipment), то это хорошее название.VolCh
30.09.2016 18:17Собственно, да, у меня большая часть core не имеет специализации, что чётко ложилось на предметную область, то было выделено. Здоровые куски инфраструктуры были выделены. И просто осталось то, что нет смысла выносить ни в сервис (грубо — ради таблички из 7 строк поднимать СУБД, апп и веб-сервер, как-то лениво), ни дублировать в нескольких сервисах.
Fesor
30.09.2016 01:37+1Если есть Core — значит на нем завязаны все (ну или большинство), он центр зависимостей. А такого не должно быть в рамках микросервисов, распределенная же система, децентрализованная. Это примерно как god object.
sentyaev
30.09.2016 18:35Да, почему-то проще сделать именно физическую границу между разными частями приложения. Без этого, границы модулей/частей приложения постоянно нарушают.
Хотя с другой стороны у нас есть все инструменты, чтобы предотвратить это, например NDepend (если говорить например про .NET, уверен для мира Java таких тулов должно быть несколько и отличного качества).
G-M-A-X
30.09.2016 20:49Хм.
А как сервисам между собой общаться? :)
Часто это сервер очередей или сервис, которы знает, как в кого ходить.
Если же они будут безобразно ходить друг в дружку, то это только увеличение бардака, с которым мы якобы пытались бороться :)
В общем, в неумелых руках любая технология будет порождать проблемы. :)Fesor
01.10.2016 11:08Часто это сервер очередей или сервис, которы знает, как в кого ходить.
вы сейчас описываете штуки вроде enterprise service bus и это тип устаревшая модель.
Обычно сервисы ходят друг в друга по сети, неиболее популярный вариант — старый добрый http. Многие используют штуки аля zeromq. То есть нет единого "сервиса" который знает как кто куда общается, ибо это сервис завязал бы всех на себе и являлся бы узким местом.
Если же они будут безобразно ходить друг в дружку, то это только увеличение бардака, с которым мы якобы пытались бороться :)
Именно друг в дружку. Если по аналогии, посмотрите картинку. В ней кружочки одинакого цвета представляют составные части микросервисов (у нас их на картинке 3) а жирные стрелочки между ними — это как они ходят по сети.
В целом микросервис должен быть самодостаточен настолько, что бы посадить на каждый отдельную команду разработчиков.
В общем, в неумелых руках любая технология будет порождать проблемы. :)
Согласен полностью. Микросервисы это последний тренд к сожалению. Модно это.
lega
01.10.2016 13:57То есть нет единого «сервиса» который знает как кто куда общается
А если сервис на который завязаны другие, сменит ip/dns, ходить и вручную менять конфиги, или как?
это сервис завязал бы всех на себе и являлся бы узким местом.
Сделать несколько нод с репликацией, чтобы не быть узким местом.Fesor
01.10.2016 15:04А если сервис на который завязаны другие, сменит ip/dns, ходить и вручную менять конфиги, или как?
ну так… в чем проблема? Не надо завязываться на то что может резко поменяться и все) Ну а так да, можно сервис дискавери замутить.
Сделать несколько нод с репликацией, чтобы не быть узким местом.
можно конечно, но всеравно по итогу все завязаны на один способ общения. А так можно эксперементировать. Где-то простой http, где-то zeromq с бинарными протоколами, где-то еще что-то.
zirix
28.09.2016 20:30>Такое невозможно сделать с монолитом.
Возможно, если он спроектирован правильно.
Вот, может быть интересно:
https://ru.wikipedia.org/wiki/Проблемно-ориентированное_проектирование
Source
29.09.2016 00:00Какая связь между DDD и применением разных ЯП в одном проекте?
Насколько я понимаю, если кусочек проекта может быть скомпилирован или задеплоен независимо от основного проекта, то это уже микросервис.zirix
29.09.2016 00:17Хорошо спроектированный монолит раздробить несложно, в т.ч. вынести часть функционала в микросервис на другом языке.
DDD одна из вещей которая этому(возможности дробления) способствует.
Я это имел ввиду.Fesor
29.09.2016 00:35Продолжу кидать ссылки на видосики: Eric Evans — DDD & Microservices: At Last, Some Boundaries!. Тут хорошо раскрыта связь между DDD и микросервисами.
p.s. вы как бы и правы и нет. Ну то есть если вы проектируете монолит, вы можете париться о bounded context-ах но с микросервисами это выходит явно потому что… ну если этого не делать то все будет… плохо. Явные границы лучше неявных.
С другой стороны если разработчик не понимает как правильно сделать монолит — в микросервисах ему точно делать нечего. Микросервисы как бы… дают профит в плане масштабируемости. И если у вас база данных влезет на один сервер или команда не настолько большая что тесно, то наверное не стоит лезть в это болото.
hlogeon
29.09.2016 08:06+1В это болото можно и нужно лезть и из собственного интереса, но не на деньги работодателя(если он сам не просил, конечно), само собой, и уж точно после освоения базовых принципов DDD. Тогда:
а) Появляется представление о том, когда микросервисы не нужны, а когда будут вполне себе неплохим решением
б)+ к скилу проектирования(в т.ч монолитных приложений)
в) Практический опыт ДО реальной необходимости
Спасибо за видео!G-M-A-X
30.09.2016 21:10Нужно заранее понимать, нужен ли сервис в данной ситуации или нет.
Иначе это напоминает перебор индекса массива (больше/меньше, строгое/нестрогое неравенство), чтобы программа заработала. :)
Понимания 0.
Мало у кого есть личные проекты (хотя это плюс, а то имеем сапожников без сапог), а тем более требующие микросервисов.
>Практический опыт ДО реальной необходимости
Это типа умение дрочить? :)
В реальности это все разобъется в пух и прах.
В реальности придется думать в каждом конкретном случае, как резать монолит.
Фреймворки за вас это не сделают.
Кмк, вещи нужно использовать по мере необходимости и с пониманием.
У меня тоже был дурной опыт. Например, с ООП. Молодой неокрепший ум (+без опыта коммерческой разработки еще) начитался, что это круто: наследование тебе, инкапсуляция.
Ну и начал натягивать ООП (так был сделан, слава богу, только один подраздел).
На поверхности был как бы ООП. Но это был ад. Я код вообще перестал понимать. :)
Плюнул потом и переписал так, как понимаю.
То есть:
Не нужно пытаться что-то использовать, потому что так все делают. Та плевать, как кто делает.
Не нужно свой код подстраивать под что-то, не понимая этого чего-то.
А также, наверное, не стоит советовать новичкам идти по пути непонимания и наименьшего сопротивления.
Нужно меньше догм.
Но это не значит, что не нужно интересоваться новыми подходами. Нужно. Только применять их с пониманием.hlogeon
30.09.2016 21:56Нужно заранее понимать, нужен ли сервис в данной ситуации или нет.
Нет. В целях обучения мы можем выделять эти сервисы искуственно. Нет ничего дурного в том, что бы в собственных проектах пробовать разные подходы и получать практический опыт их применения.
Мало у кого есть личные проекты (хотя это плюс, а то имеем сапожников без сапог)
Разработчик без личных проектов — тоже самое, что адвокат без судебной практики. Это как
разработчик без аккаунта guthub и знания английского. Право на существование само собой имеет, но это уж точно не то к чему стоит стремиться.
В реальности это все разобъется в пух и прах.
У меня например не разбилось, что я делаю не так?
В реальности придется думать в каждом конкретном случае, как резать монолит.
Очевидно, однако, если ты пользуешься одними и теми же архитектурными принципами, то этот процесс будет, как минимум унифицирован. Вот был у меня DDD проект. Взял, да повыдергивал домены на микросервисы. Часа 2 заняло с учетом написания Dockerfile.
Фреймворки за вас это не сделают
Проектирование это и не задача фреймворков.
Это типа умение дрочить? :)
Это не умение дрочить, это подкрепление теоретической базы практикой, что является стандартным в процессе обучения практически любому навыку.
Первый раз мы решаем квадратное уравнение до реальной необходимости это сделать(у многих такая необходимость не возникает вообще никогда).
Кмк, вещи нужно использовать по мере необходимости и с пониманием.
Да, в таком случае при возникновения этой самой необходимости ты делаешь миллионы ошибок, которые такой же программист УЖЕ преодалел, изучая и практикуясь.
На поверхности был как бы ООП. Но это был ад. Я код вообще перестал понимать. :)
Ну я до первого опыта коммерческой разработки использовал ООП и даже все эти абстрактные фабрики, стратегии и прочие синглтоны. Может всетаки дело не в необходимости а отсутствии у кого-то системного подхода к собственному обучению?
Не нужно пытаться что-то использовать, потому что так все делают
Нужно хотя бы понимать, что они делают и почему они это делают. А еще лучше уметь это делать тоже. Тогда у тебя будет хотя бы шанс оценить, нужно ли оно тебе или нет. А иначе получается поведение 14-летнего подростка в духе: «ФУ, микросервисы мейнстрим, лучше буду дерьмо жрать с кучей инстансов монолитных приложений, зато НИКАК ФСЕ»
Та плевать, как кто делает
Ну это вообще какой-то вброс дерьма на вентилятор. Стандарты? Паттерны? Лучшие практики? Что объединят три предыдущих вопроса? Это именно то «как делают другие» и разработчику на это не должно быть плевать.
Не нужно свой код подстраивать под что-то, не понимая этого чего-то
Обратного никто не утверждал.
А также, наверное, не стоит советовать новичкам идти по пути непонимания и наименьшего сопротивления.
Этого им тоже никто не советовал, ну, во всяком случае, я точно не советовал.
Нужно меньше догм
Назовите хоть одну — уберем.
Но это не значит, что не нужно интересоваться новыми подходами. Нужно. Только применять их с пониманием.
Для того, что бы у тебя появилось понимание, тебе нужно сначала их как минимум использовать :)
Повторю еще раз начало своего сообщения:
В это болото можно и нужно лезть и из собственного интереса, но не на деньги работодателя
G-M-A-X
01.10.2016 15:01>Нет. В целях обучения мы можем выделять эти сервисы искуственно.
Обучение без необходимости — это дерьмо. Человек ни хрена не поймет.
Знания получил, думать не научился. :)
Прежде всего нужно учить думать.
>Разработчик без личных проектов — тоже самое, что адвокат без судебной практики.
Совсем не то. И это сплошь и рядом.
>У меня например не разбилось, что я делаю не так?
Может это Вам лишь так кажется? :)
>Проектирование это и не задача фреймворков.
Уже нет? Не они задают архитектуру? :)
>Первый раз мы решаем квадратное уравнение до реальной необходимости это сделать
Сравнение некорректное.
Решая квадратное уравнение мы решаем конкретную задачу: найти x.
Здесь же абстрактное обучение в вакууме.
Еще раз:
Есть потребность — делаем, нету — не делаем.
Не нужно искусственно что-то натягивать.
>Да, в таком случае при возникновения этой самой необходимости ты делаешь миллионы ошибок, которые такой же программист УЖЕ преодалел, изучая и практикуясь.
Программист, пишущий на фреймворках? :)
Та они (в основном) и шагу ступить без него не могут.
Я не спорю, что нужна практика. Но эта практика не должна быть надуманной и без понимания. Тогда это не практика. А сферический вакуум.
>Может всетаки дело не в необходимости а отсутствии у кого-то системного подхода к собственному обучению?
1. Я не считаю себя супер-программистом.
2. Необходимости в ООП не было, а я поддался моде. (Ну как вы советуете сейчас идти пилить микросервисы :) )
Если Вы применяли с пониманием (хотя Вы говорите, что без :) ) и оно было необходимо (хотя в случае с микросервисами Вы говорите, что нет), то ок :)
>ФУ, микросервисы мейнстрим, лучше буду дерьмо жрать с кучей инстансов монолитных приложений, зато НИКАК ФСЕ.
Я такого не говорил.
Я всегда говорю: Все нужно использовать по потребности и с умом! А не искать серебрянные пули.
>Назовите хоть одну — уберем.
Вы сами их упомянули:
«Стандарты? Паттерны? Лучшие практики?»
А также: ООП — тру (в последнее время: ФП — тру), фреймворки — тру, goto — зло.
Ну не везде это нужно и оправдано. Тем более без понимания.
>Обратного никто не утверждал.
Как же. Вы же советуете играть с микросервисами без необходимости в них (а значит понимания нету).
>Ну это вообще какой-то вброс дерьма на вентилятор. Стандарты? Паттерны? Лучшие практики? Что объединят три предыдущих вопроса? Это именно то «как делают другие» и разработчику на это не должно быть плевать.
Разработчик, который не умеет думать, а использует готовую догматику, не понимает, что он делает.
На поверхности получаем якобы и стандарты, и паттерны, и практики, только оно такое говнокодное, что капец. Ну или несвязная копипаста из разных мест :)
Это обезьяна, а не разработчик.
Серебрянной пули нету, а вы всем ее суете.
>Для того, что бы у тебя появилось понимание, тебе нужно сначала их как минимум использовать :)
Нет.
Нужно читать стоящие книжки, смотреть примеры, делиться опытом.
Иначе это будет варение в себе.
На поверхности будут вроде и микросервисы, только сторонний наблюдатель подумает: ну нахера это тут?
Если человек применяет подход без понимания, то он обезьяна.
>В это болото можно и нужно лезть и из собственного интереса, но не на деньги работодателя
Я согласен, что заниматься экспериментами на деньги работодателя не стоит.
Я против этого и выступаю, когда крутые перцы говорят: а не переписать ли все на A фреймворк, а не поменять ли нам БД, а не добавить сюда еще эту приблуду.
Хотя необходимости в этом нет, просто им скучно.
Если же есть необходимость, то вряд ли ваш личный проект будет больше требовать разбиения на микросервисы (а они нужны не такому и большому количеству сайтов).hlogeon
01.10.2016 15:20+1Я Вас помню из предидущих тем, мое прошлое сообщение — лишь послание тем, кто будет его читать. У меня нет никакой необходимости вам что-то доказывать) Уймитесь уже наконец. Добра <3
Если же есть необходимость, то вряд ли ваш личный проект будет больше требовать разбиения на микросервисы
Мой личный проект в среднем обрабатывает 10к запросов в секунду, думаю, на этом можно закончить :DG-M-A-X
01.10.2016 15:371. Я тоже помню (фрагментарно) :)
2. Не нужно ничего доказывать. Я не стараюсь что-то доказать. Я стараюсь найти аргументацию, что для чего в каких случаях больше подходит, в каких случаях А может быть лучше Б, в каких нет.
В данном случае — в каких случаях и как стоит использовать микросервисы.
3. Если я в чем-то ошибаюсь, приводите аргументы. Но не детский лепет, который разбивается в пух и прах. (Это не только вам адресовано). Если укажете на ошибку, я будут только благодарен.
>Мой личный проект в среднем обрабатывает 10к запросов в секунду, думаю, на этом можно закончить :D
Ну это совсем другой разговор. :)
Мало какие коммерческие имеют такие показатели (а подавляющее большинство и не имеет). Вы могли двигаться в сторону микросервисов, большинство же нет. :)
Но нужно смотреть, что скрывается за этими запросами. :)
Тут https://habrahabr.ru/post/262623/ тоже крутые цифры, а под капотом работа с первичным ключом одной таблицы.
Не надо экстраполировать свою самоуверенность на все отрасли человеческой деятельности.Fesor
01.10.2016 16:12Не надо экстраполировать свою самоуверенность на все отрасли человеческой деятельности.
Золотые слова. Возможно для вас они тоже должны прозвучать. Просто поверьте что в мире есть люди которые знают что делают.
G-M-A-X
01.10.2016 17:401. А я и не говорил, что я не могу ошибаться. Перечитайте пункты 2,3, адресованные предыдущему оратору.
2. Люди, которые знают, что делают, конечно же есть. Я этого тоже не отрицал :)
Но не все то золото, что блестит:
Например.
То, что проект большой, не значит, что он умно сделан (тем более во всем). :)
Посмотрите для примера на богомерзкую мордокнигу.
G-M-A-X
30.09.2016 21:41Масштабировать само приложение не так сложно (в этом не такая большая нужда).
И режут на микросервисы не только из-за масштабируемости, а и:
а) чтобы не было блокировок, когда вместо синхронного выполнения тяжелой операции выполняютт ее в фоне.
б) когда был монолит, но мы захотели предоставлять API доступ к нему: мобильное приложение, сторонние клиенты.
А вот базу сложнее масштабировать.
У кого-то есть данные, сколько занимают главные таблицы пользователей в ВК и ФБ? :)
Основная поболь, кмк, невозможность выполнить запрос над данными более одного сервера.
Хотя тут: https://habrastorage.org/getpro/habr/post_images/a07/038/4e5/a070384e516dd5466ee15fc314b1dc44.png
https://habrahabr.ru/company/oleg-bunin/blog/309330/
как бы есть решение.
А также есть малоизвестный mysql-движок FEDERATED.
Мне интересен такой вопрос:
Как будет работать шардинг с группировками по данным из нескольких шард? :)
Потому что обычные запросы можно выполнить и отдельно на каждом сервер.
Работают ли межсерверные джойны (хотя это ад)?
А также:
Стоит ли делать шардинг по UUID (когда большинство запросов именно по UUID) и кто как его делает.
Есть ли range ранжирование?
Source
29.09.2016 11:53Хорошо спроектированный монолит раздробить несложно
Спасибо, кэп.
В комментарии, на который Вы в начале ветки ответили, обратного и не утверждалось )))
mikhailt
29.09.2016 15:01Мой опыт говорит, что это ужасная практика.
Это дорого, потому что сложно. Сложность следует из многгобразия.
Когда тут ява, тут пхп, тут Си а, тут дядька на баше накорябал так, что никто не разберет — получается зоопарк технологий. И на каждую технологию вам нужны: специалисты, обновления, лицензии, сервера и т.д. А дядька на баше уволился — и все ищи ветра в поле…
Плавали, знаем.
Идеально иметь одну серверню технологию и один скрипт язык.
lesha_firs
29.09.2016 15:36+1Нет. ЯП (язык программирования) это инструмент, а инструмент нужно использовать по назначению. Если ваш продукт большой то вам не избежать большого зоопарка ЯП. Посмотрите на крупные компании Google, Яндекс… у них ставка сделана на архитектуру а не на ЯП.
yara_73
30.09.2016 00:08Ну я сомневаюсь, что статья рассчитана на людей которые работают в Google и решают архитектурные проблемы такого порядка, вот и ответ рассчитан на ту же аудиторию, а там и вправду на одном человеке держится модуль и для начальства большая проблема заменять работников под специфичный инструмент, тогда и гвозди забивают микроскопом, потому что так дешевле и риски меньше.
Cryvage
30.09.2016 06:17ЯП (язык программирования) это инструмент, а инструмент нужно использовать по назначению.
Никто и не спорит, что язык надо подбирать под задачу. Это, можно сказать, уже стало мантрой среди программистов. И принцип этот, конечно же, правильный. Весь вопрос в том, что считать задачей. Чем она определяется? По сути, задача определяется, так называемым, условием задачи. Есть главное условие, собственно что нужно сделать, а есть уточняющие условия, накладывающие дополнительные ограничения, и добавляющие свою специфику. Так вот, наличие у компании уже готовой кодовой базы на каких-то языках, и специалистов, знакомых с определенными языками и технологиями, тоже является частью условия. И если какой-то язык или фреймворк более-менее подходит, и он уже используется в других проектах, то лучше не вводить новых сущностей. И тут нет никакого противоречия с принципом «инструмент под задачу». Мы как раз выбираем инструмент под нашу задачу. Не под какой-то архетип задачи, а под нашу конкретную задачу, учитывая все условия.
Что до крупных компаний, типа Google, то у них есть свои особенности, связанные с их размером. Наверное зоопарк технологий для них неизбежен. Но успеха они достигают вовсе не благодаря ему. Скорее уж вопреки. Ставка на архитектуру — это как раз инструмент борьбы с негативными эффектами от зоопарка.VolCh
30.09.2016 18:26+1И если какой-то язык или фреймворк более-менее подходит, и он уже используется в других проектах, то лучше не вводить новых сущностей.
А потом оказывается, что кодовая база монолита на устаревших языках/фреймворках (или их версиях) разрослась настолько, что только за поддержку нужно платить большие деньги, а переписать вообще практически не реально.
Ну или даже без устаревания, на этапе постановки начальной задачи фреймворк более-менее подходил, но с годами, по мере изменения задачи всё менее и менее, а переход на более подходящий становится всё дороже и дороже.
В общем, однозначного «лучше» точно не может быть. Влияет на лучше слишком многое, чтобы давать универсальные советы.G-M-A-X
30.09.2016 21:18Старению подвержены все… :)
Старение не так страшно, когда можешь сам омолаживать по необходимости (самопись).
В случае умирания фреймворка/CMS, выхода новой несовместимой версии поимеем боль :)
Зоопарк сложнее поддерживать.
Сотрудники слабо взаимозаменяемы.
Выгоды от зоопарка больше у крупных компаний.
Dimusik
28.09.2016 13:45+1Как всегда, истина где-то посередине. Микросервисы же не обязывают использовать себя для очередного блога. Весь вопрос в поставленной задаче. В любом случае всегда нужно включить голову и подумать.
belurd
28.09.2016 14:18+3На мой взгляд, многие «недостатки» перечисленные в статье ровно так же свойственны и для монолита. К примеру, в #4 перечислены сложности с написанием интегрейшн тестов и «социальные проблемы» с ответственностью за баги. Что одно, что другое может быть свойственно и для микросервисов и для монолита. Приведение таких «недостатков» в поддержку своего мнения выглядит больше как «накидаю-ка еще на вентилятор».
sshikov
28.09.2016 19:29+1Просто у этого поста другой посыл. Микросервисы не решают некоторые проблемы, про которые принято считать, что они как раз должны это делать.
То что монолитная архитектура этого не делает тоже — мало что меняет. Это просто значит, что у таких проблем совсем другие решения.
Scf
28.09.2016 14:26+6Да, в принципе, всё совпадает с моим опытом использования микросервисов. Вот только статья совершенно не раскрывает вопрос "зачем тогда вообще с этим связываться".
Мой ответ — повторное использование уже сделанной работы. Рассматривайте микросервисы как библиотеки 2.0 со следующими преимуществами:
- интегрировать микросервис проще, чем библиотеку. Никаких конфликтов, никаких зависимостей, никакой головной боли с конфигурированием. Есть сетевое API по известному протоколу.
- библиотека позволяет повторно использовать алгоритмы. Микросервис позволяет повторно использовать еще и данные без многих недостатков интеграционной СУБД (см. Фаулера Integration database antipattern)
- микросервисы, в отличие от библиотеки, позволяют скрыть свои зависимости от клиентов. Это позволяет писать как более гибкие, так и более устойчивые приложения. Например, микросервис отправки писем единственный хранит настройки email-сервера и может предпринимать дополнительные усилия по доставке писем.
- как обобщение предыдущего пункта, микросервисы изолируют проблемы конфигурирования кода. Те же адреса SMTP, баз данных, JMS… Большой монолит частенько имеет весьма обширную конфигурацию.
- гораздо богаче возможности по версионированию. Система может одновременно использовать несколько разных версий одного и того же микросервиса, если не все клиенты не готовы делать миграцию. Не разных версий API, а именно разных версий бинарника с несовместимыми API.
Про цену микросервисов хорошо написано выше. Да, нужно будет сильно вложиться в инфраструктуру. Да, проектирование интерфейсов микросервисов — это очень сложная и ответственная задача, так что лучше начать с монолита. Но я считаю, что в большинстве случаев оно того стоит.
Oxoron
28.09.2016 16:45+1Рекомендуете сделать монолит, а потом потихоньку вытаскивать из него микросервисы?
Scf
29.09.2016 11:33Да, тот же Фаулер много про это пишет. Выделение микросервиса — это большая ответственность, т.к. нужно стремиться к тому, чтобы любая доработка системы затрагивала минимальное количество микросервисов. А это требует глубоких знаний системы, которые как правило появляются уже после её написания.
sshikov
28.09.2016 19:35интегрировать микросервис проще, чем библиотеку
На мой взгляд — одинаково. Если библиотеке нужен был параметр конфирурации — то у микросервиса он никуда не денется, просто вы его сконфигурируете в другом месте.
микросервисы изолируют проблемы конфигурирования кода.
И кудаж они их девают по-вашему? На мой простой взгляд, если у монолитного приложения наружу торчит скажем один http-порт, то у микросервисов их потенциально будет по числу самих сервисов. И где тут уменьшение проблем конфигурирования?
гораздо богаче возможности по версионированию.
И гораздо сложнее протестировать все возможные варианты и сочетания версий.
Я в целом к тому, что даже если все эти преимущества вдруг реализуются в жизни (что бывает не всегда) — они все равно будут чего-то стоит. Т.е. это не бесплатно.
skiedr
28.09.2016 22:38>> микросервисы изолируют проблемы конфигурирования кода.
> И кудаж они их девают по-вашему?
sarcasm on
Да все просто — добавляем микросервис конфигурирования всей инфраструктуры.
sarcasm off
К сожалению в крупных проектах так и делают.
Scf
29.09.2016 11:44Конечно не бесплатно, просто нужно выбирать решения, которые дают больше плюсов, чем минусов :-) По пунктам, местами гиперболированно:
- пусть нам нужно отправлять письма. В случае библиотеки мы имеем конфигурацию e-mail сервера в 10 местах и много работы при смене e-mail провайдера, в случае микросервиса — конфигурация одна, код интеграции с email — один
- service discovery. В рамках системы должен быть единый механизм поиска сервиса по имени и авторизации. В этом плане есть различие между внутенними сервисами (микросервисы) и внешними сервисами(почта/база/JMS/...) Т.к. первые контролируются вами, что означает унифицированный интерфейс, обратную совместимость, отсутствие хитрых параметров конфигурации и необходимости мигрировать на альтернативные реализации.
- Тестирование — это отдельный большой разговор. Вкратце, моё мнение — микросервисы должны тестироваться изолированно на соответствие своему контракту API. Плюс какие-то базовые приемочные тесты всей системы. К сожалению, полные приемочные тесты часто становятся узким местом — из-за быстродействия, объема и ограниченного кол-ва людей, которые с ними работают.
sshikov
29.09.2016 11:56+1Простите, но почему "монолит" — это вдруг сразу один класс или один метод? Там тоже как правило есть модули, и там тоже конфигурация e-mail сервера в одном месте а не в 10. Другие варианты возможны — но это не монолит, а клиника. Так нормальные люди уже не делали, когда и этого слова микросервис никто не знал.
Грубо говоря, я уже лет 10 назад вполне себе делал приложение из скажем пяти десятков EJB, каждый из которых занимался своим делом. У них был свой (внутренний, обычно) API, и они вполне себе повторно использовались. JavaEE контейнер, внутри которого сотни модулей — это микросервисы, или еще нет? :) А OSGI, где сотни бандлов, в том числе многие нескольких версий параллельно — это все еще оно?
Успешная попытка выделить то же самое как отдельный сервис означает как правило, что это просто очень типовой сервис, вроде упомянутого вами e-mail, который действительно всем нужен. За пределами приложения.
Но это автоматически означает одну простую вещь — если вы это вынесли наружу и опубликовали, вы становитесь поставщиком этого сервиса. Со всей вытекающей ответственностью. Захотели изменить что-то? Ан нет — нельзя, потребители не готовы. Выкатывайте другую версию, рядом, а эту продолжайте поддерживать. Тут могут быть и плюсы, и минусы — но они далеко не всегда так очевидны и примитивны, и далеко не все чисто технические.
Scf
29.09.2016 12:43Мне не пришлось поработать над большим (большой=нет ни одного человека, который знает детали функционирования всех модулей) монолитным проектом — будет интересно, если вы прокомментируете его недостатки, как я их вижу :-)
- прибитые гвоздями технологии. Старая джава, старые версии библиотек, которые достаточно сложно заменить на более новые.
- недостаточный уровень изоляции. Всё приложение работает на одном общем пуле ресурсов, и ошибка в одном модуле может уронить/испортить всё приложение
- Большое время старта приложения
- Большой объем конфигурации, сложное управление зависимостями между модулями
Основная идея микросервисов — это декомпозиция. То, что сервисом можно пользоваться, не изучая его исходники и зависимости.
И я совсем забыл про главное преимущество микросервисной архитектуры — устойчивость. Кластер из микросервисов может переживать аппаратные и программные сбои любого характера, более "мягко" реагирует на перегрузку, может терять функциональность частично, позволяет деплоймент без даунтайма, разнообразные разноцветные тестирования и т.п.
sshikov
29.09.2016 13:05Старые технологии — это все имеет место, само собой. Например, есть у нас большой проект, сделанный на старых технологиях. Некоторые из них уже и на сайте разработчика найти проблематично — настолько устарели, документация либо удалена, либо в архиве. Смигрировать его на более новые — очень сложно. Хотя реально это OSGI с кучей модулей, которые вполне независимы друг от друга. И с библиотеками реально проблем мало. Сложно смигрировать инфраструктуру — т.е. например OSGI сам по себе, или допустим Spring/Camel etc.
Но с другой стороны — мне сложно представить, что бы было, если бы вместо контейнера (с общей инфраструктурой типа мониторинга и управления) была бы пара сотен микросервисов. Не вижу, почему бы объему работы снизиться.
Насчет уровня изоляции — ну это тоже не факт, что недостаток. Общим пулом ресурсов может быть проще управлять, чем скажем распределить память (которая все равно ограничена) между множеством независимых компонентов, когда вы не знаете, сколько конкретно каждому из них нужно.
Время старта? Ну да, был случай в практике, когда томкат стартовал на настольной машине минут 15 — занимаясь это время тем, что закачивал в память огромный кеш. Только это не время старта монолита — это время старта де-факто одного сервиса. Ну вот такой сервис, да. И потом, чтобы сократить время старта, вам нужно, чтобы микросервисы были реально независимы друг от друга. А то представьте — ядро стартовало, очень быстро, но половина функций недоступна, потому что старт части сервисов еще в процессе. Это само по себе может быть немаленькой проблемой.
Конфигурация? Ну опять же — я совершенно не вижу причин, почему ее должно стать меньше. Наоборот — если у меня условно "монолит", то в нем скажем есть JMX (и консоль типа hawtio), и вся конфигурация и управление — там. А если у меня сотня сервисов — то у меня сотня JMX, и управление сотней сервисов. Т.е. число точек конфигурирования и управления не имеет тенденции сокращаться, если мы не сокращаем функциональность. Скорее уж наоборот.
Ну и напоследок — возможно, для меня просто "монолит" это давно уже то, что правильнее называть "контейнер", т.е. JavaEE или OSGI. И он в жизни давно кластер, он деплоится на лету, и т.д и т.п. А настоящего своего монолита я много лет и не видел пожалуй.
Scf
29.09.2016 13:36Микросервисы можно мигрировать по одному, микросервисы можно вообще не трогать, пока они работают. И даже когда придет необходимость дописывать микросервис, одновременно релизить всех его клиентов необязательно — можно задеплоить и старую, и новую версию.
В плане утилизации ресурсов на каждый модуль/микросервис — это забота админа и нагрузочного тестирования. Да, это требует соответствующего мониторинга.
Современное приложение должно стартовать 2-3 секунды, не больше. Иначе теряется flow при разработке. Поддерживает ли osgi параллельный старт разных модулей?
Мониторинг и агрегация мониторинга — это отдельная работа, которая в случае микросервисов делается долго, но один раз. Изменения конфига налету через JMX — имхо, плохая идея, т.к. теряется воспроизводимость релиза. В случае редеплоя мы можем эти настройки и не применить и получим неожидаемое поведение. Что касается точек управления — микросервис должен быть задеплоен один раз и просто работать, не требуя каких-либо подкручиваний. При правильной декомпозиции, объем конфигов перед релизами должен уменьшаться.
Да, монолит как один здоровенный кусок лапши, индустрия, к счастью, уже оставила позади. Пожалуй, в настоящее время монолитом можно назвать EE/OSGI приложения, которые не рискуют деплоить отдельными модулями, а только целиком.
sshikov
29.09.2016 14:14OSGI поддерживает все что угодно. Можно стартовать по очереди, можно остановить половину. Это именно что микросервисы в их самом явном виде. Но при этом это еще и контейнер.
Что до времени старта — то я не зря приводил пример. Есть приложения, которые стартуют минутами. Это их работа такая. И это вообще не показатель ничего.
Я подозреваю, что мы просто имеем дело с разными типами приложений. У меня вполне нормально, что приложения подкручиваются регулярно. На них влияет рынок, и его нужно учитывать — и хорошо бы не при помощи релизов.
Пожалуй, в настоящее время монолитом можно назвать EE/OSGI приложения, которые не рискуют деплоить отдельными модулями, а только целиком.
Ну, к сожалению, я такие знаю. IBM BPM — это такое вот JavaEE, которое состоит всего порядка из пяти EAR, и при этом не просто деплоится только целиком, а еще и предполагает, что мы кучу всего в контейнере (Websphere) понастроим, чтобы оно завелось.
Tramvai
28.09.2016 20:39+3Было бы не плохо еще и рассказать какой оверхед стоит за использованием микросервисов.
- Деплоймент новых версий
- Транзакции и ролбеки
- Агрегаторы
- Логирование ошибок
- Авторизация
- Общий код, который используют разные версии сервисов
- Обработка и вывод ошибок
- Разработка внутренних стандартов для request/response
Scf
29.09.2016 11:48Да, это еще и неполный список! Но современная инфраструктура — это очень обширная тема, которую обсуждаяемая статья немножко затрагивает. Точно не формат комментариев.
apelsyn
28.09.2016 14:55Как-то однобоко получилось.
Есть монолит, есть сервисы, есть монолит+сервисы. И то, и то востребовано в разработке.
minamoto
28.09.2016 15:56Поясните, что означает фраза
умение писать ленивый и некачественный код снижается
Вот это:
your ability to write lazy or poorly thought out code decreases
мне кажется, тоже не очень хорошо сформулировано, но хотя бы понятно, что хотел сказать автор — он имеет в виду, что уменьшается возможность писать плохой код. И «poorly thought out» — это не «некачественный», а «непродуманный», хотя бы.
relgames
28.09.2016 16:04+1Популярный подход — строить архитектуру таким образом, что логические «сервисы» владеют частями предметной области.
У нас примерно так и сделано. По сути, получаются сервисы из монолитов, связанные через REST и AMQP.
Плюсы подобного подхода несомненны: жесткое разделение баз данных, открытый API, которым могут пользоваться не только мы, более быстрые тесты. Раньше прогон всех тестов монолита занимал минут 30, теперь модули собираются параллельно.
Изолированность — это круто, на самом деле. Например, нам пришлось переписать часть модулей с Cassandra на MySql, и это прошло практически незаметно для остальных сервисов, т.к. REST API не поменялся.old_bear
28.09.2016 20:50+1Изолированность — это круто, когда вы с самого начала чётко представляете себе как делить функциональность на куски. А когда это представление сильно меняется по ходу игры, то начинается веселье, про что автор собственно и пишет.
Предвидя возражение вида «просто надо верхний уровень проектировать с первого раза правильно», сразу отвечу, что это очень часто зависит не от проектировщиков а отлевой пяткизаказчика.G-M-A-X
28.09.2016 22:11Просто не нужно делать культ карго из микросервисов, а использовать их с умом, когда это действительно необходимо. :)
relgames
29.09.2016 10:29Мы некоторые сервисы делили пополам, а некоторые объединяли. Не без проблем, но все прошло достаточно гладко.
Самый важный урок — API должен быть доступен через некий центральный роутер (у нас — haproxy), тогда даже дробление/слияние модулей слабо повлияет на видимый api.
G-M-A-X
28.09.2016 17:36Везде нужно подходить с умом.
А то заставь дурака богу молиться. :)
>Например, входящие API-запросы, фронтэнд панели управления и фоновые задачи могут находиться в одной кодовой базе, но не обязательно на каждой машине обрабатывать все три типа запросов.
На самом деле это микросервис :)VolCh
28.09.2016 21:09+1Это отмасштабированый монолит с балансером по урл скорее.
G-M-A-X
28.09.2016 22:03Просто зачем каждый раз городить огород, если можно использовать ту же кодовую базу?
С таким успехом монолитом нельзя считать 2 системы, работающие на одном фреймворке. :)
А вообще какая разница что это: отмасштабированный монолит / чистейший микросервис.
Разве отмасштабированный монолит не может в придачу общаться посредством очереди кроме балансировки по урл?
Главное, чтобы задачи решало.
У кого-то микросервисы могут ходить в одну базу / писать/читать одни и те же файлы.
У кого-то все изолировано (как при использовании сторонних API).Fesor
28.09.2016 23:42если можно использовать ту же кодовую базу?
Специально для вас: Greg Young — Stop Over-Engenering
У кого-то микросервисы могут ходить в одну базу / писать/читать одни и те же файлы.
в этом случае микросервисы превращаются в распределенный монолит. У вас узкое место (одна база данных) так и остаются.
Source
29.09.2016 00:22У вас узкое место (одна база данных) так и остаются.
Справедливости ради, база данных далеко не всегда является узким местом.
G-M-A-X
29.09.2016 00:30>Специально для вас: Greg Young — Stop Over-Engenering
Мне влом смотреть 50 минут.
Вы хотите сказать, что я проповедник оверинжиниринга? :)
Вроде во всем спорах, в т.ч. с Вами, я выступаю против него. :)
>в этом случае микросервисы превращаются в распределенный монолит. У вас узкое место (одна база данных) так и остаются.
Плевать.
Нам что завести 2-100500 баз данных с пользователями для каждого микросервиса, который с ними работает?
Выйдет что-то на постном масле. :)
Блин, в прошлом моем комменте
«С таким успехом монолитом нельзя считать 2 системы, работающие на одном фреймворке. :)»
следует читать так:
«С таким успехом микросервисом нельзя считать 2 системы, работающие на одном фреймворке. :)»Fesor
29.09.2016 12:19Вы хотите сказать, что я проповедник оверинжиниринга? :)
Ну от части. И я тоже. Я думаю вам понравится, посмотрите)
Вроде во всем спорах, в т.ч. с Вами, я выступаю против него. :)
вот потому я ссылку и даю. Вопервых далеко не все ваши высказывания чушь) Во вторых — мы по разному трактуем оверинженеринг.
Нам что завести 2-100500 баз данных с пользователями для каждого микросервиса, который с ними работает?
нет. Будет одна база данных с пользователями и каждая база данных для себя будет хранить кусочек информации которая нужна ей. Денормализация и все такое.
И да, это сложно и для 99.9% проектов это не нужно. Но зато позволяет вам более гибко подходить к процессу разработки системы.
aosja
28.09.2016 21:29Сервис, как класс, если много торчит наружу, тора пора задуматься над рефакторингом :)
Микросервисы особенно хороши, если замешать все на каком-нибудь messaging в виде транспорта (для легкости broadcast/unicast обмена) и приправить auto discovery (для минимизации конфигурации зависимостей)Scf
29.09.2016 12:08Банки любят такую архитектуру, т.к. она гарантирует отсутствие потерь данных и имеет солидное теоретическое обоснование. Но — очереди хранят данные, их нужно конфигурировать (в частности, роутинг между топиками), они могут переполняться, в них быть данные устаревшего формата/мусор(queue poisoning), их содержимое частенько сложно просмотреть, в системах на очередях требуются дополнительные усилия для того, чтобы связать запрос с ответом.
aosja
29.09.2016 13:00Просто взять любой message broker и использовать, как транспорт — много нерешенных проблем. Тут вы абсолютно правы. Очереди, конфигурация… Но варианты решения, все же, есть. Например, в своем
велосипедепроекте у меня пока получилось использовать messaging (NetMQ, по факту, p2p), реализовать «синхронное» получение ответа на запрос и auto discovery, т.е., необходимо сконфигурировать только well-known адрес дискавери-сервиса.Scf
29.09.2016 13:38А в чем преимущество ZeroMQ перед обычным синхронным RPC в такой схеме? И как же гарантия доставки, особенно при падении брокера?
aosja
29.09.2016 14:02Центрального брокера нет, p2p. Если нужно подтверждение доставки, можно указать callback и дождаться синхронно его получения, что не всегда надо. Discovery service использует broadcast для мониторинга состояния нод в сети, удобно было использовать PUB/SUB. В принципе, основная идея заключалась в использовании раутинга (только) на основании типа передаваемого сообщения (а также его версии), так что вариант с NetMQ казался наиболее подходящим.
Fesor
28.09.2016 23:41+1сначала мы любим микросервисы, потом мы их ненавидим, и потом понимаем когда и как стоит строить архитектуру основываясь на этой идее. Ну как с паттернами в целом.
afiskon
29.09.2016 11:08+1Несколько лет писал микросервисы и в итоге пришел к тем же выводам, что и автор. Как обычно с новыми блестящими технологиями — много хайпа и размахивания руками, мало здравого смысла. В это время суток мне кажется оправданным следующими подход. Если есть монолит, и с ним нет проблем, оставляем монолит. Если с ним есть проблемы, думаем, можно ли решить их НЕ распиливая монолит на сервисы. Если единственное решение в распиливании — распиливаем на сервисы разумного размера (не обязательно микро).
wiz
29.09.2016 14:01Независимо масштабируемые части должны быть независимы. А уж микро или макро они получатся — не суть важно.
afiskon
29.09.2016 15:50Ну тут проблема в том что из-за изменяющихся бизнес требований типа очевидно независимые части внезапно становится зависимыми и наоборот. Пример из практики. Есть аккаунты, они друг с другом никак особо не связаны, можно смело пошардить по ним. Проходит два года и бизнес придумывает реферальную программу из-за которой транзакции на одном аккаунте приводят к изменению на втором аккаунте, и далее по реферальным ссылкам. Внезапно на ровном месте возникли распределенные транзакции между шардами. И это еще не самый сложный пример — логика вычисления комиссии вообще как угодно может меняться, сегодня она одни данные использует, завтра совершенно другие.
Это я к тому что по дэфолту лучше монолит, см выше.Gugic
29.09.2016 19:54Если у вас уже все на сервисах, значит просто добавится сервис транзакций, который в том числе будет отслеживать целостность данных в течение всей транзакции и после нее. В монолите вам также скорее всего придется изрядно перекроить абстракции, чтобы добавить такой функционал.
Fesor
29.09.2016 21:29по дэфолту лучше монолит, см выше.
С этим спорить не буду и полностью поддерживаю. Важно просто понимать когда микросервисы все же нужны.
Внезапно на ровном месте возникли распределенные транзакции между шардами.
между микросервисами. И решение для этой проблемы уже давно придумали — Saga и да это сложно (в рапределенных то системах). И да, каждый микросервис теперь должен уметь откатывать результат своих действий. И да, у нас сверху будет сидеть отдельный микросервис который трекает результат работы каждого и если где-то что-то пошло не так — просит откатиться.
afiskon
30.09.2016 11:21Помимо Saga еще придумали транзакции на CAS. Не то, чтобы шибко сложно, и стороннего сервиса не требует. При аккуратной реализации дает snapshot isolation. См также тынц.
Fesor
30.09.2016 13:01Хм… интересно. А разве это работает не на уровне базы данных? Ну то есть… да. у вас есть та же распределенная касандра, и да вы моете там так сделать. Но у меня есть 2 микросервиса, один использует эту распределенную касандру а другой neo4j. Ну то есть… разве транзакции на CAS не расчитаны что у нас общая распределенная база данных?
Scf
30.09.2016 14:54Необязательно из-за этого связываться с распределенными транзакциями. Есть варианты попроще:
- Рефералы как-нибудь переживут, если из-за сбоя системы им недоначислят несколько посещений. Выбирая между временем разработки системы распределенных транзакций и небольшими потерями для нескольких клиентов раз в n месяцев… возможны варианты варианты.
- Использовать persistent queue. В случае с реферралами не так нужна атомарность и не нужна возможность отката транзакции — так что можно вместе с обновлением аккаунта послать в очередь сообщение о том, что надо обновить рефералов.
А вообще с деньгами надо аккуратнее обращаться. Понимать немного бухгалтерию, двойную запись, проводки. И строить архитектуру по аналогии с тем, как работают с финансами в реальном мире. Все-таки жизнь — она распределенная, асинхронная и транзакций там не предусмотрено :-)
lega
29.09.2016 23:33+1Я думаю автор пришел (предлагает) немного другое, не просто монолит, а «внутренних» сервисов на основе чистых, хорошо определенных модулей в коде", как бы микросервисы, но внутри, где внутренний микросервис можно будет легко* вынести во внешний. Хоть это и монолит, но его можно отнести к 3-му виду,
weekens
06.10.2016 17:08Зацепился глазом за одну неточность.
Они работают быстрее ввиду простых факторов вроде компиляции.
Если говорить про NodeJS, то он компилирует JavaScript в нативный код во время запуска (с заглушками, правда). Компиляция в JVM-языках — это компиляция в байт-код. Чтобы он стал нативным кодом, необходим «прогрев» — JIT компилятор должен сообразить, что этот код горячий (вызывается часто), и только после этого происходит компиляция в нативный код. Это вовсе не является преимуществом в плане производительности.
SirEdvin
Хм, как раз недавно был вопрос по поводу микросервисов.
Если кодовая база самого микросервиса относительно небольшая и он делает одну, но сложную задачу, а сам docker-образ вместе с зависимостями весит больше 5ГБ, это тоже будет микросервис?
maxru
Да, микросервис. Про микрообраз никто и не говорил :)
P.S. NodeJS? :))
SirEdvin
Хм, мне кажется, количество зависимостей тоже должно быть в определении, но… нет так нет.
P. S. Нет, просто OpenCV + нейронные сети + еще какая-то штука и вуаля :)
pragmader
Там же файловая система слоями, если вы используете один и тот же базовый образ, скажем node.js, то он скачается и установится только раз, остальные просто переиспользуют это в своих слоях.
Никогда не видел, чтобы самый верхний слой весил больше чем 100 МБ.
Fesor
Микро определяется областью ответственности а не размером. Вполне нормальный микросервис.