Спринт 1/14: Понимание профессии системного аналитика → Тема 6/9: Компоненты клиент-серверной и микросервисной архитектуры → Урок 2/2
Монолитная и микросервисная архитектуры
В этом уроке вы узнаете, что такое микросервисная архитектура, чем она отличается от монолитной и каковы особенности работы системного аналитика при разработке в микросервисной архитектуре.
Микросервисная архитектура — это способ построения приложения в виде набора слабо связанных между собой компонентов («микросервисов»).
Микросервисную архитектуру противопоставляют монолитной (или «монолиту»). В монолитной архитектуре не выделяют микросервисы, всё приложение реализуется цельным «куском». У монолитного приложения единый сервер приложений, один сервер баз данных. У микросервисного приложения может быть несколько маленьких серверов приложений и серверов баз данных.
Микросервисную архитектуру отличают два основных принципа — слабая связанность и единая ответственность.
Принцип слабой связанности (Low сoupling) подразумевает, что один микросервис не должен зависеть от реализации другого. Микросервис предоставляет другим микросервисам API. Если API остаётся неизменным, реализовывать микросервис можно как угодно, например, написав его на другом языке программирования.
Сильная и слабая связанность
Что это значит?
Представьте кухню ресторана, с которой посетитель (в IT — пользователь) взаимодействует через меню (в IT этому соответствует API). Посетитель видит в меню сырники со сметаной, делает заказ, заказ передаётся на кухню. Ему всё равно, как именно готовят эти сырники — жарят на сковородке или запекают в духовке, главное — чтобы они были вкусными. Кухня может сменить способ приготовления сырников, и на посетителя это не повлияет — позиция в меню и результат останутся такими же. Это и есть пример слабой связанности: посетитель (пользователь) зависит только от наличия сырников в меню (API микросервиса), но не зависит от способа их приготовления (реализации). Он даже не узнает, как именно готовят сырники.
Представьте другую ситуацию — посетитель увлекается приготовлением сырников. Попробовав вариант сырников с рикоттой, он через официанта передаёт указания повару: сахара недостаточно, яйца должны быть только перепелиными, вместо рикотты лучше использовать творог, с каждой стороны нужно жарить (а не выпекать!) не дольше четырёх минут, при подаче посыпать сахарной пудрой. В этом случае посетитель сильно связан с кухней — теперь он зависит не только от API (меню, в котором указано конкретное блюдо), но и от реализации (как именно это блюдо готовят). Требования посетителя влияют на способ приготовления сырников (четыре минуты, а не две, например), рецепт (творог вместо рикотты) и способ подачи (посыпать сахарной пудрой). В такой ситуации кухне сложно поменять рецепт или способ приготовления, не нарушив обязательства перед посетителем, который поделился с кухней своим рецептом сырников.
Как и меню хорошего ресторана, API правильно спроектированного микросервиса должен содержать все нужные запросы (в меню должны быть необходимые блюда) и возвращать в ответе нужные данные (блюда должны быть хорошо приготовлены), чтобы у клиентов и других микросервисов (посетителей) не было необходимости погружаться в детали реализации. Такой расклад хорош и для посетителя — ему предоставляют качественный сервис, где не нужно разбираться в деталях, и для команды разработки — у неё не связаны руки по модернизации. Главное — чтобы API микросервиса (то есть перечень того, что он может выполнить) не менялся.
Принцип единой ответственности (Single-responsibility principle) подразумевает, что микросервис решает только одну задачу — и в полном объёме. Если микросервис отвечает за рассылку уведомлений пользователям приложения, он должен решать эту задачу «от и до» — в приложении не должно быть аналогичной функциональности. В то же время в микросервисе не должно быть функциональности, которая никак не связана с рассылкой уведомлений.
Как это работает? Например, в Chatty есть функциональность для оплаты обучения. Оплачивать можно банковскими картами, через систему быстрых платежей и различные платёжные системы. Функцию оплаты можно реализовать в виде отдельного микросервиса.
Согласно принципу слабой связанности, микросервис оплаты должен предоставлять другим компонентам приложения программный интерфейс (API), который позволит им направлять заказ на оплату и получать результат — статус оплаты (заказ либо оплачен, либо нет). Остальная платёжная механика — выбор способа оплаты, взаимодействие с платёжной системой и прочее — заложена внутри микросервиса оплаты и недоступна другим компонентам приложения.
Если для использования Chatty потребуется добавить ещё один способ оплаты или возможность оформления кредита на обучение, это никак не повлияет на остальную часть приложения — все изменения будут внутри микросервиса оплаты, его API не поменяется.
Согласно принципу единой ответственности, в микросервисе оплаты не должно быть ничего лишнего — того, что с оплатой не связано. На входе у микросервиса оплаты имеются только номер заказа, его сумма и сведения о плательщике, на выходе — статус оплаты.
Дополнительный бонус: микросервис оплаты Chatty можно повторно использовать для другого приложения, так как он слабо связан с остальной частью приложения Chatty.
Преимущества и недостатки микросервисной архитектуры
Микросервисная архитектура помогает справиться с нарастающей сложностью. Эта проблема рано или поздно настигает любое активно развивающееся приложение. Как правило, какое-либо приложение сначала выстраивается в монолитной архитектуре (пока оно маленькое, нет смысла разбивать его на микросервисы), но по мере его развития возникают сложности:
- Трудности с координацией работы команды. Если 10 разработчиков вместе работают над программным кодом приложения, их работу можно организовать так, чтобы никто друг другу не мешал. Как только эту работу выполняют 100 разработчиков, организовать их уже гораздо сложнее.
- Снижение надёжности. Ошибка в одном месте может привести к неработоспособности всего приложения. Чем больше приложение, тем больше у него уязвимых мест, где можно допустить ошибку.
- Изменения технологий и языков программирования. Если приложение разрабатывалось на языке Perl, который был популярен 20 лет назад и забылся сегодня, его и дальше придётся развивать на языке Perl. При этом сейчас трудно найти разработчика, который не только знает этот язык, но и готов на нём работать. Чтобы сменить язык программирования, потребуется переписать приложение целиком, а это долго и дорого.
- Затраченное время. В микросервисной архитектуре процессы происходят быстрее. У большого монолитного приложения процедуры сборки и установки могут занимать десятки минут — это очень долго. Даже простое действие — открыть программный код проекта — у разработчика может занять 10 минут, в течение дня он откроет код ещё много раз.
Эти факторы не означают, что микросервисная архитектура лучше монолитной. У микросервисной архитектуры есть и свои недостатки. Она решает проблемы, которые возникают по мере усложнения приложения, но создаёт другие трудности:
- Для обработки запроса пользователя потребуется в определённом порядке вызвать несколько микросервисов. Для этого в архитектуре приложения возникают новые компоненты, которые управляют порядком вызова микросервисов при обработке запросов пользователей. Увеличение числа компонентов и правил их взаимодействия усложняет архитектуру приложения.
- Усложнение процедуры установки приложения. Не получится ограничиться одним сервером приложений и одним сервером баз данных, понадобится много — для каждого микросервиса. Без DevOps-инженера не обойтись.
- Микросервисное приложение может работать лишь частично. Монолитное приложение либо работает, либо нет — это легко проверить. Микросервисное приложение состоит из десятков или сотен независимых микросервисов, и некоторые его части могут не функционировать, не влияя на работу других. Например, неработоспособность сервиса рассылки никак не скажется на возможности оформления заказов. Чтобы оперативно выявлять проблемы, нужны специальные средства мониторинга, которые ещё сильнее усложняют архитектуру приложения.
- Возможность разрабатывать микросервисы на разных языках программирования может стать недостатком. При отсутствии контроля проект может превратиться в лоскутное одеяло.
- Необходимость реализации компенсирующей логики. Например, в сервисе Яндекс Еда при получении заказа нужно принять оплату (через микросервис оплаты), переслать заказ в ресторан (через микросервис размещения заказов) и назначить курьера для его доставки (через микросервис доставки). Что делать, если оплату мы приняли, заказ в ресторане разместили, а курьера найти не смогли — все заняты? Нужно продумывать такие сценарии на этапе проектирования приложения.
Что должно делать приложение, если микросервис доставки недоступен? Можно подождать некоторое время и попробовать ещё раз. Но сколько ждать и сколько раз пробовать? Это всё тоже нужно продумывать при проектировании.
В каждом конкретном случае нужно взвешивать преимущества и недостатки и решать, нужна микросервисная архитектура или нет.
Особенности работы системного аналитика при разработке в микросервисной архитектуре
Одна из типовых задач нашего времени — «переход от монолита к микросервисам». Она возникает в том случае, когда организация долгое время развивала приложение в монолитной архитектуре. Приложение усложнилось, и для решения этой проблемы организация меняет его монолитную архитектуру на микросервисную.
Это сложная задача — разом перевести большое приложение на микросервисную архитектуру невозможно. Перевод происходит поэтапно: из приложения один за другим выделяют микросервисы. При этом важно не нарушать работу приложения — оно всё время должно быть доступно для пользователей.
Особенности работы системного аналитика при микросервисной архитектуре приложения:
- Работа становится «двухслойной» — нужно проектировать как всё приложение в целом (из каких микросервисов оно состоит и как они взаимодействуют между собой для решения задач пользователя), так и каждый отдельный микросервис (как он устроен и что делает).
- Увеличивается количество задач по проектированию API и порядку взаимодействия микросервисов между собой и со сторонними приложениями.
- Необходимо глубже погружаться в архитектуру приложения — из каких микросервисов оно состоит и как они взаимодействуют между собой.
- Нужно больше думать об ошибках и нештатных ситуациях. Если в монолитных приложениях есть стандартные решения для их обработки, то в микросервисных — вариантов решения много.