Microservices: Mezinahî girîng e, hetta ku we Kubernetes hebe

19 сентября в Москве pêk hat первый тематический митап HUG (Highload++ User Group), который был посвящён микросервисам. На нём прозвучал доклад «Эксплуатация микросервисов: размер имеет значение, даже если у вас Kubernetes», в котором мы поделились обширным опытом компании «Флант» в области эксплуатации проектов с микросервисной архитектурой. В первую очередь он будет полезен всем разработчикам, задумывающимся о применении этого подхода в своём настоящем или будущем проекте.

Microservices: Mezinahî girîng e, hetta ku we Kubernetes hebe

Nasandin vîdyoya raporê (50 минут, гораздо информативнее статьи), а также основную выжимку из него в текстовом виде.

NB: Видео и презентация доступны также в конце этой публикации.

Pîrozbahiyê

Обычно хорошая история имеет завязку, основной сюжет и развязку. Этот доклад больше похож на завязку, причём трагическую. Также важно отметить, что в нём представлен взгляд на микросервисы со стороны kedmêjî.

Начну с такого графика, автором которого (в 2015 году) bûye Martin Fowler:

Microservices: Mezinahî girîng e, hetta ku we Kubernetes hebe

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

Дополню этот график для случая использования Kubernetes:

Microservices: Mezinahî girîng e, hetta ku we Kubernetes hebe

Почему приложению с микросервисами стало лучше? Потому что такая архитектура выдвигает серьёзные требования к архитектуре, которые в свою очередь отлично закрываются возможностями Kubernetes. С другой стороны, часть этой функциональности будет полезна и для монолита, особенно по той причине, что типичный на сегодняшний день монолит — это не совсем монолит (подробности будут далее в докладе).

Как видно, итоговый график (когда и монолитное, и микросервисное приложения в инфраструктуре с Kubernetes) не очень-то отличается от изначального. Далее речь будет идти о приложениях, эксплуатируемых с использованием Kubernetes.

Полезная и вредная микросервисность

И тут главная мысль:

Microservices: Mezinahî girîng e, hetta ku we Kubernetes hebe

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

Microservices: Mezinahî girîng e, hetta ku we Kubernetes hebe

Если называть её bikartê, то на другой стороне графика будет вредная микросервисность (мешает работе):

Microservices: Mezinahî girîng e, hetta ku we Kubernetes hebe

Возвращаясь к «главной мысли»: стоит ли вообще доверять моему опыту? С начала этого года я посмотрел 85 проектов. Не все они были микросервисными (такой архитектурой обладали примерно от трети до половины из них), но это всё равно большое число. Нам (компании «Флант») как аутсорсерам удаётся видеть широкое разнообразие приложений, разрабатываемых как в маленьких компаниях (с 5 разработчиками), так и в крупных (~500 разработчиков). Дополнительным плюсом является то, что мы видим, как эти приложения живут и развиваются на протяжении многих лет.

Зачем микросервисы?

На вопрос о пользе микросервисов есть весьма конкретный ответ у уже упомянутого Martin Fowler:

  1. чёткие границы модульности;
  2. независимый деплой;
  3. свобода выбора технологий.

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

Microservices: Mezinahî girîng e, hetta ku we Kubernetes hebe

Если описать «в ощущениях» некоторые из пунктов, то:

  • чёткие границы модулей: вот у нас есть страшный монолит, а теперь всё будет аккуратно разложено по Git-репозиториям, в которых всё «по полочкам», не перемешано тёплое с мягким;
  • независимость деплоя: мы сможем выкатывать сервисы независимо, чтобы разработка шла быстрее (параллельно публиковать новые фичи);
  • независимость разработки: мы можем отдать этот микросервис той команде/разработчику, а тот — другой, благодаря чему сможем быстрее разрабатывать;
  • большая надёжность: если случится частичная деградация (упадёт один микросервис из 20), то перестанет работать лишь одна кнопка, а система в целом продолжит функционировать.

Типовая (вредная) микросервисная архитектура

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

Примером будет служить абстрактный интернет-магазин, собирающийся конкурировать с Amazon или хотя бы OZON. Его микросервисная архитектура выглядит так:

Microservices: Mezinahî girîng e, hetta ku we Kubernetes hebe

По совокупности причин, эти микросервисы написаны на разных платформах:

Microservices: Mezinahî girîng e, hetta ku we Kubernetes hebe

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

Microservices: Mezinahî girîng e, hetta ku we Kubernetes hebe

Каковы её последствия?

У Fowler’а и на этот счёт есть статья — о «расплате» за использование микросервисов:

Microservices: Mezinahî girîng e, hetta ku we Kubernetes hebe

А мы посмотрим, оправдались ли наши ожидания.

Чёткие границы модулей…

di heman demê de сколько микросервисов нам в действительности нужно поправить, чтобы выкатить изменение? Можем ли мы вообще разобраться, как всё работает, без распределённого трассировщика (ведь любой запрос обрабатывается половиной микросервисов)?

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

Microservices: Mezinahî girîng e, hetta ku we Kubernetes hebe

Независимость деплоя…

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

Свобода выбора технологии…

Она есть. Только стоит помнить, что зачастую свобода граничит с беспределом. Очень важно здесь не выбирать технологии только для того, чтобы «поиграть» с ними.

Независимость разработки…

Как сделать тестовый контур для всего приложения (из такого множества компонентов)? А ведь ещё надо его поддерживать в актуальном виде. Всё это приводит к тому, что реальное количество тестовых контуров, которое мы в принципе можем содержать, оказывается минимальным.

А развернуть всё это локально?.. Получается, что зачастую разработчик делает свою работу независимо, но «наугад», потому что вынужден ждать, когда освободится контур для тестирования.

Раздельное масштабирование…

Да, но оно ограничено в области используемых СУБД. В приведённом примере архитектуры не будет проблем у Cassandra, но будут у MySQL и PostgreSQL.

Большая надёжность…

Мало того, что в действительности вывод из строя одного микросервиса зачастую ломает корректное функционирование всей системы, так есть ещё и новая проблема: сделать отказоустойчивым каждый микросервис очень сложно. Потому что в микросервисах используются разные технологии (memcache, Redis и т.п.), для каждого нужно всё продумать и реализовать, что, конечно, возможно, но требует огромных ресурсов.

Измеримость нагрузки…

С этим действительно всё хорошо.

«Лёгкость» микросервисов…

У нас не только появились огромные сетевые накладные расходы (приумножаются запросы на DNS и т.п.), но и из-за множества подзапросов мы начали реплицировать данные (хранить кэши), что привело к значительному объёму хранилищ.

И вот каков итог соответствия нашим ожиданиям:

Microservices: Mezinahî girîng e, hetta ku we Kubernetes hebe

Но и это ещё не всё!

Bo:

  • Скорее всего нам потребуется шина сообщений.
  • Как сделать консистентный бэкап на нужный момент времени? Единственный rast вариант — выключить трафик для этого. Но как это сделать на production?
  • Если идёт речь о поддержке нескольких регионов, то организовать устойчивость в каждом из них — очень трудоёмкая задача.
  • Появляется проблема внесения централизованных изменений. Например, если нам нужно обновить версию PHP, то потребуется сделать коммит в каждый репозиторий (а их — десятки).
  • Рост операционной сложности навскидку получается экспоненциальным.

Что со всем этим делать?

Начинайте с монолитного приложения. Опыт Fowler’а dibêje о том, что практически все успешные микросервисные приложения начинались с монолита, который стал слишком большим, после чего и был разбит. В то же самое время практически все системы, построенные как микросервисные с самого начала, рано или поздно испытывали серьёзные проблемы.

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

Но что делать, если мы уже оказались в такой ситуации?

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

Если в случае разросшегося монолита (когда у нас закончилась возможность докупать для него ресурсы), мы его разрезаем, то в данном случае получается обратная история: когда чрезмерная микросервисность уже не помогает, а мешает — отрезайте лишнее и укрупняйте!

Например, для рассмотренного выше собирательного образа…

Избавьтесь от самых сомнительных микросервисов:

Microservices: Mezinahî girîng e, hetta ku we Kubernetes hebe

Объедините все микросервисы, отвечающие за генерацию фронтенда:

Microservices: Mezinahî girîng e, hetta ku we Kubernetes hebe

… в один микросервис, написанный на одном (современном и нормальном, как вы сами считаете) языке/фреймворке:

Microservices: Mezinahî girîng e, hetta ku we Kubernetes hebe

У него будет один ORM (одна СУБД) и сначала пара приложений:

Microservices: Mezinahî girîng e, hetta ku we Kubernetes hebe

… а вообще туда можно перенести гораздо больше, получив такой результат:

Microservices: Mezinahî girîng e, hetta ku we Kubernetes hebe

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

Bi kurtahî

Посмотрите на картину шире. Очень часто все эти проблемы с микросервисами возникают из-за того, что кто-то взял свою задачу, но хотел «поиграть в микросервисы».

В слове «микросервисы» часть «микро» является лишней. Они «микро» лишь по той причине, что меньше огромного монолита. Но не надо думать о них как о чём-то маленьком.

И для финальной мысли вернёмся к изначальному графику:

Microservices: Mezinahî girîng e, hetta ku we Kubernetes hebe

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

Vîdyo û slaytên

Видео с выступления (~50 минут; к сожалению, оно не передаёт многочисленные эмоции посетителей, что во многом определяло настроение доклада, но уж как есть):

Pêşkêşkirina raporê:

PS

Raporên din ên li ser bloga me:

Вероятно, вас также заинтересуют следующие публикации:

Source: www.habr.com

Add a comment