Введение
Очень техническая статья для программистов и тех, кто понимает как устроена разработка.
Перед началом хотелось бы отметить, что данная тема очень спорная и вызывает горячие баталии в интернете прямо как и другие похожие темы: что такое legacy, что такое enterprise. А все потому, что четких общепринятых критериев тут мало, они сильно размыты, и каждый добавляет от себя что-то еще.
Конечно, эта статья очередное мнение, но даже этот небольшой кусок информации был обдуман в голове ни один десяток раз. И итоговая картина родилась при обсуждении и общении с другими программистами. Так что, с данным мнением ниже согласен не один человек, поэтому оно имеет право на публикацию.
Что такое монолит
Во-первых, монолит – это не плохой код или что-то из разряда плохой практики. В самом этом слове нет ничего отрицательного. Просто подход и ничего более.
Во-вторых, многие программисты сходятся во мнении, что монолит – это некая большая вычислительная система с единой кодовой базой, в которой объединены все бизнес-задачи (бизнес-логика).
Вы смотрите на проект и понимаете что тут все намешано как в супе. Хотя можно было некоторые части поделить на системы и подсистемы. Это видно невооруженным глазом с призмы небольшого опыта сложной разработки.
Самый простой пример монолита – это большинство проектов на PHP и Laravel с использованием Vue.js (или React). Когда фронтенд и бекенд являются одним целым. Когда в шаблонах blade используются Vue.js компоненты вперемешку с PHP кодом. А там где-то ведь еще существует слой с бизнес-логикой для всего этого. Огромный слой.
Паттерн MVC в программировании часто порождает монолиты (Laravel это изначально голый MVC). А если еще начать имплементировать туда какие-то большие экосистемы (по типу реактивных фреймворков), то можно потом гарантированно получить монолит.
Монолит вызывает ощущение огромной и жестко взаимосвязанной системы, что не всегда хорошо. Гибкость и масштабирование теряется. Мы бы сказали, что возможность горизонтального масштабирования остается: Вы ведь дальше можете обслуживать систему и увеличивать ее функционал новыми фичами. Но вот вертикальное масштабирование (более точечное для каждого элемента) теряется.
Давайте снова взглянем на классический проект на Laravel и Vue.js. Теперь представьте: Вам надо внедрить туда SSR (рендеринг JavaScript на сервере). Как Вы это сделаете? На сколько сильно придется изуродовать проект? Если не успели представить, вот статья с примером. Выглядит все очень страшно.
В-третьих, монолит взывает к техническим ограничениям куда больше, чем микросервисы: Вы заперты в рамках одной технологи. И если нужно создать взаимодействие между другой, то начинается боль, хардкор и технический долг. Как раз наш пример выше, где мы рассказали про SSR и PHP отлично показывает весь спектр проблемы.
Монолитность на первых порах слабо ощущается в универсальных языках программирования по типу Node.js, Kotlin, Java. Ведь на этих языках можно выйти за пределы серверов. Но когда язык более узконаправленный как PHP или Perl, то можно быстрее столкнуться с проблемами.
Что такое микросервисы
Существует нереально огромное количество определений, но каких-то общепринятых доктрин тут тоже нет.
Во-первых, микросервисы – это не “круто” и не “плохо”. Для большинства проектов это “фиг пойми”. Это просто такой же подход как и монолит, тут есть свои минусы и свои плюсы, которые еще раскрываются со временем в больших проектах.
Во-вторых, многие программисты согласны с тем, что микросервисы – это несколько приложений, объединенных в одно.
Вы смотрите на проект и понимаете… что ничего не понимаете. Запрос летит на распределитель, который проксирует его на какой-то из нескольких серверов, чтобы дальше данные передались в другое место и только потом сложились в базу данных… которая тоже где-то в другом месте, на другой машине.
Для примера давайте возьмем снова наш любимый PHP, Laravel и реактивный фреймворк Vue.js. Нам также нужен SSR. Как это будет в монолите мы рассказали, теперь расскажем как это может быть при другом подходе.
Допустим, в один сервис мы выделяем Vue.js и Node.js. Он будет отвечать чисто за интерфейс сайта и серверный рендеринг. Напишем мы серверный рендеринг сами или используем фреймворки по типу Nuxt.js, Quasar – неважно. Бизнес логики тут не будет, наш фронтенд будет обращаться по API к бекенду (второму сервису) и отдавать уже готовую HTML пользователю после компоновки данных.
Во второй сервис мы вынесем наш бекенд (PHP и Laravel или вообще что-то другое). Тут будет происходить вся магия с данными. Они будут как-то обрабатываться, складываться в базу данных и так далее.
Наш результат работы пока еще нельзя назвать микросервисами (личное мнение автора), но это уже точно сервисная архитектура. А далее, при масштабировании, можно все превращать в очень сложное и высоконагруженное приложение: добавить Kubernetes; добавить распределить запросов; размазать наш фронтенд с SSR на несколько машин, дабы ускорить получение данных пользователями при их наплыве; размазать наш бекенд на несколько машин, дабы первый сервис c SSR быстрее получал данные при высокой нагрузке; вынести базу данных на отдельный сервер; добавить Redis для кеша и сессий и тоже вынести в отдельный сервер для отказоустойчивости. И вот, уже пахнет микросервисами.
Понимаете, это ведь еще не все. Можно наш бекенд (второй сервис) тоже поделить на модули: один будет написан на Go и отвечать за самые высоконагруженные операции, например, запросы к базе (или лучше к кэшу) для получениях основных страниц сайта. Остальное: регистрацию, авторизацию, работу в личном кабинете можно оставить на PHP. При росте нагрузок можно дробить дальше: нужно увеличить скорость ответа, переносим часть функционала кода на Go; нужно увеличить количество обработанных подключений, докупаем сервера и снова размазываем наше приложение по еще большему количеству серверов.
Что лучше
Однозначного ответа тут не существует. Если кто-то говорит (без привязки к примеру), что монолит плохо, а микросервисы – круто, и наоборот, то он идиот.
Нужны ли микросервисы калькулятору? Думаем нет. Смог бы Авито с огромным трафиком обойтись без микросервисов? Думаем нет. Везде нужна мера и умение работать головой.
Автор статьи придерживается подхода, в котором хотя бы бекенд и фронтенд нужно поделить на разные сервисы. В нашей компании фронтенд делатся на реактивных фреймворках, поэтому это обосновано. Мы создаем приложение так, дабы бекенд (API) и интерфейс были независимыми друг от друга. Чтобы в случае чего это легко масштабировалось: чтобы перевести фронтенд с Vue.js на Angular, чтобы переехать с PHP на Node.js, Kotlin, Go. Ну и не обязательно пихать это все по разным серверам, но хотя бы в разные контейнеры в том же Docker.
Так что, думайте головой, исходите из своих задач и выбирайте лучшее решение самостоятельно.
Рассказать друзьям: