Микросервисы

13 June 2024
Rate this item
(0 votes)

Наверняка ты постоянно слышишь про микросервисы. Микросервисы то, микросервисы сё, переписали все на микросервисы, развернули микросервисы в контейнерах. А че это вообще такое? Ща все объясним. Чтобы понять как сейчас, надо понять как было раньше. А раньше стандартным путем разработки приложения была так называемая монолитная архитектура, или просто монолит. Это означает, что все компоненты приложения, то есть по сути весь код были частью одного большого проекта. Давай возьмем к примеру какое-нибудь приложение - пусть это будет интернет магазин по продаже корма для животных. Тут у нас есть разные функции - например каталог товаров, корзина, страница оплаты, авторизация если вы постоянный покупатель, и отправка нотификаций о скидах на элитный корм для капибар. И весь код для этих функций - будет находиться в одном проекте, или как еще говорят - в одной кодовой базе. То есть это будет одно монолитное приложение. Вся эта балалайка разрабатывается и выкатывается как один нераздельный блок. Вот так раньше все и писали код, а затем подумали: “ээм, кажется что-то тут не так”. На практике же, когда приложения становились большими, оказалось, что такие системы сложно поддерживать, сложно внедрять новые функции, масштабироваться и прочее. Программистов вообще хлебом не корми, дай все пооптимизировать, попереиспользовать и обмазать абстракциями. Поэтому, придумали как сделать поудобнее - была создана многоуровневая архитектура, в которой приложение разделялось на логические уровни, в зависимости от функций кода. Часто применялась трехуровневая модель: уровень Представления или Presentation, где находился код отвечающий за то, что видит пользователь, и тут тусили фронтендеры. Далее шел логический уровень, он же Logic, где находился код, в котором была описана вся бизнес-логика приложения, сюда уже доступ был только по пропуску бекендера, и наконец уровень данных или Data - где находилось все, что имело отношение к хранению данных.

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

Понимаешь к чему все идет? Правильно, надо все разделить на несколько кусочков! Это и будет микросервисная архитектура. Тут смысл в том, что мы разбиваем наше одно большое приложение на несколько маленьких независимых частей, эдакие мини-программы, которые называются сервисами. Вообще, обычно принято выделять сервисы основываясь на их функционале - то есть в идеале один сервис выполняет одну бизнес-задачу. Так в нашем примере мы можем выделить отдельно сервис авторизации, который будет отвечать за регистрацию и логин пользователей, сервис каталога, который будет отдавать из базы список товаров, сервис корзины, который будет хранить покупки, сервис оплаты, который будет связан с платежной системой, сервис уведомлений, который будет посылать пуш или смс сообщения, сервис того, что ты поставил лайк этому видео и подписался на канал - ну и так далее. Получается, что-то вроде конструктора, где каждый сервис это отдельный блок. Снаружи как будто ничего не меняется, но
внутри, теперь когда пользователь будет делать запрос, он будет передаваться на выполнение в свой отдельный сервис. При этом каждый сервис является автономной независимой единицей. То есть их можно разрабатывать, деплоить и масштабировать независимо от других, прикручивать свои разные базы, даже писать его на другом языке, несмотря на то, что они часть одного общего приложения. Обычно каждый микросервис имеет свою отдельную базу данных, либо отдельную схему в общей базе данных. Возвращаясь к нашему примеру с фильтром: теперь ты легко можешь обновить только сервис каталога, раз изменения только были только там. И так же теперь можно заскейлить сервис оплаты подняв несколько экзепляров этого сервиса на время пиковой нагрузки, не трогая остальные. Ну и если ты все сделал по красоте, то падение одного сервиса, может пройти относительно безболезненно. Ошибка в сервисе авторизации? Неприятно, не получится зарегаться на сайте, но купить нужный корм все еще можно! При этом сервисам все еще нужно общаться друг с другом: например, чтобы получить данные которых у них нет, или сообщить, что на их стороне все сделано, и надо продолжить выполнение логики.Тут есть несколько вариантов, в зависимости от задачи. Во первых, каждый сервис должен иметь свой API по которому к нему можно обратиться, чтобы он сделал какую-то задачу. Так сервисы могут общаться между собой, делая HTTP или gRPC запросы. Такой способ называется синхронной коммуникацией - когда мы отправляем запрос и ждем, что нам ответят с той стороны. Например, при переходе к оплате, мы сначала обратимся к сервису корзины, чтобы получить все, что в нее положили, а затем к сервису каталога, спросив, а все ли оттуда сейчас есть в наличии. И если все ок, то можем двигаться и передавать данные в сервис оплаты, а если чего-то нет, то вернуть пользователю сообщение с предупреждением. Сервис каталога при этом может иметь много различных методов, которые могут использовать разные сервисы - например, одному нужно получить данные о товарах по айдишникам, другому количество определенного товара, третьему нужен отфильтрованый список категорий товаров и так далее. Короче все то же самое что и обычное приложение с апи, только поменьше. Еще перед всеми сервисами обычно ставят такую штуку как API Gateway, он нужен чтобы пользователи делали запросы не на сами сервисы, а сначала на него, а он уже маршрутизировал их. Еще один вариант общения - это асинхронная коммуникация, когда нам не нужно ждать ответа от сервиса. Тут сообщения шлются к какому-то брокеру по типу RabbitMQ (рэбит эм кью) или Kafka (кафка), они попадают там в очередь, а затем принимаются сервисом, который вычитывает эту очередь и там уже выполняются нужные действия. При этом, отправитель не ждет ответа, он идет работать дальше. В нашем примере это может быть событие оплаты, и мы хотим отправить клиенту смс уведомление об этом, но не хотим ждать пока сервис уведомлений соберет все данные, отправит их в смс сервис-провайдер, получит оттуда ответ и ответит нам - это не столь критично, чтобы тормозить процесс из-за этого. Поэтому, мы отправляем сообщение в очередь и идем заниматься своими делами дальше, например показывать покупателю что оплата прошла, а сервис уведомлений отработает когда отработает. Вот так вот! Очень модно и молодежно. Но как всегда тут есть и обратная сторона луны. Одних сложностей становится меньше, зато появляются другие. Так нам теперь нужно поднимать и настраивать каждый сервис отдельно, и связывать их друг с другом. Тут нужно подходить с умом к архитектуре. Особенно важно обращать внимание на консистентность хранимых данных - раз микросервис обладает определенным набором данных в своей базе или схеме, то сделать джоин к другой таблице не получится - нужно собирать все по кусочкам как пазл уже на уровне логики приложения. К тому же тут не обойтись без джентельменского набора DevOps инструментов. Нам понадобится контейниризация, чтобы удобно, компактно и независимо разворачивать микросервисы. Чтобы гибко управлять всем этим зоопарком хорошо бы уметь в оркестрацию. Чтобы удобно было удобно деплоиться стоит знать как строить CI/CD пайплайны. Ну и вдобавок настроить логирование и мониторинг, чтобы в случае чего быстро находить проблемные места. Кажется не малый список, но не стоит пугаться: девопс инженеры легко могут с этим справляться. И если ты хочешь также, то записывайся на бесплатный вводный урок нашего легендарного курса по девопс по ссылочке в описании, где ты сможешь научиться работать со всеми этими инструментами и кучей других классных штук. Вот такая балалайка эти ваши микросервисы. Но стоит понимать, что это не волшебная палочка, которая решит все твои проблемы. Многие приложения до сих пор работают как монолиты. Как ты думаешь почему? Где лучше использовать монолитную архитектуру?

More in this category: Что такое SSL/TLS »

Leave a comment

Popular Posts

Advertisement

Headlines