Предлагаю поговорить о том, когда нужны микросервисы, а когда нет. Спойлер: это зависит от проекта.
У нас, разработчиков программного обеспечения, довольно интересная профессия. Мы можем спокойно кодировать целыми днями, а затем прочитать статью о чём-то — и она подвергает сомнению всю нашу работу, потому что какой-нибудь Netflix сказал XYZ.
Просто так, из-за мнения одного человека или компании вы начинаете сомневаться во всём, что делали в течение многих лет, даже если всё работало отлично.
Когда мы читаем HackerNews и другие новостные сайты, то часто видим технические сообщения от Google, Netflix, Amazon и Facebook, и они любят говорить о том, сколько сотен или тысяч сервисов они запускают. Они говорят о преимуществах всё делать по-своему. Это тенденция последних нескольких лет.
Но давайте посмотрим правде в глаза. Вряд ли у вас в наличии 1000 разработчиков, которые работают над массивным проектом с более чем 10-летней историей.
Просто потому, что Google делает это, не означает, что вы тоже должны делать это.
Мы работаем в совершенно другой галактике. Google сталкивается с проблемами, с которыми мы, вероятно, никогда не столкнёмся, но в то же время мы можем делать вещи, которые Google не может.
Как начинается большинство программных проектов?
Многие проекты начинаются с одного человека, который делает всю работу. Есть миллион примеров, но давайте посмотрим на Shopify. Изначально сервис закодировал Тобиас Лютке (он был основан на Ruby on Rails и до сих пор, кстати, работает на «рельсах»).
Как вы думаете, Тобиас сидел в нерешительности, кропотливо продумывая идеальную архитектуру на микросервисах, прежде чем написать первую строчку кода?
Чёрт, нет. Я не присутствовал при разработке первой версии Shopify, которая изначально была просто интернет-магазином для сноубординга, но если Тобиас похож на меня (типичный разработчик), то процесс выглядел примерно так:
- Изучить новую технологию в процессе написания исходного продукта.
- Написать довольно нестандартный (поганый), но полностью рабочий код.
- Посмотреть, как всё работает вместе и возбудиться.
- Провести рефакторинг типа «выжигание огнём» и улучшить код, когда возникает проблема.
- Повторять этот цикл при добавлении новых функций и запуске в рабочей среде.
Это может показаться очень простым циклом, но мне потребовалось около 20 лет программирования, чтобы понять, насколько он глубок.
Вы не становитесь лучше как программист, теоретически продумывая оптимальные настройки, прежде чем написать первую строчку кода. Вы становитесь лучше, написав много кода с абсолютным и явным намерением заменить почти всё, что пишете, лучшим кодом, как только начнёте испытывать реальные проблемы.
Тот первоначальный код, который вы заменили, не является впустую потраченным временем или усилиями. Со временем он во многом помогает вам повысить свой уровень. Это секретный ингредиент.
Поговорим об абстракциях кода
Как разработчики, мы все слышали фразу «DRY: don't repeat yourself», и в целом это разумный совет не делать работу повторно. Но часто её стоит сделать.
Её стоит повторить, когда вы пытаетесь абстрагировать что-то без полного понимания и создаёте то, что называется неполной абстракцией (leaky abstraction).
Я обычно выполняю работу трижды, прежде чем вообще ПОДУМАТЬ о рефакторинге какого-то кода и удалении дублей. Часто лишь после 4-го или 5-го раза я принимаю какие-то меры.
Вам действительно нужно несколько раз увидеть, как вы дублируете код в разных ситуациях, прежде чем станет ясно, что именно переводить в переменные и удалять из мест, где изначально прописан этот код.
Уровни абстракции, от встроенного кода до внешних библиотек:
- Написать встроенный код.
- Продублировать код в нескольких разных местах.
- Извлечь продублированный код в функции и т.д.
- Некоторое время использовать эти абстракции.
- Посмотреть, как этот код взаимодействует с другим кодом.
- Извлечь общую функциональность во внутреннюю библиотеку.
- В течение длительного времени использовать внутреннюю библиотеку.
- Действительно понять, как все части собираются вместе.
- Создать внешнюю библиотеку (open source и др.), если это имеет смысл.
Смысл в том, что нельзя «изобрести» хорошую библиотеку или фреймворк. Почти все очень успешные инструменты, которые мы используем сегодня, пришли из реальных проектов. Там наш любимый инструмент извлечён из реальных случаев внутреннего использования.
«Рельсы» — отличный пример. DHH (автор Rails) не проснулся однажды и сказал: «Ой! Пора создать директории models/, controllers/ и views/!».
Нет. Он разработал Basecamp (реальный продукт), тогда появились определённые шаблоны, и эти шаблоны были обобщены, а затем выделены из Basecamp в Rails. Этот процесс всё ещё продолжается сегодня, и, по-моему, это единственная причина, по которой Rails остаётся настолько успешным.
Это идеальный шторм очень хорошо обкатанных (читай: не теоретически разработанных) абстракций в сочетании с языком программирования, который позволяет написать привлекательный код. Это также объясняет, почему почти все фреймворки типа «Rails, только на языке XYZ» не работают. Они пропускают ключевые компоненты цепочки абстракций и думают, что могут просто дублировать Rails.
От абстракций к микросервисам
Для меня микросервисы — просто ещё один уровень абстракции. Необязательно это шаг 10 в вышеприведённом списке, потому что не все библиотеки предназначены для микросервисов, но на концептуальном уровне похоже на то.
Микросервисы — это не то, с чего вы начинаете, точно так же, как вы не пытались бы сразу создать идеальную внешнюю библиотеку с открытым исходным кодом, прежде чем написать хоть строчку кода. В этот момент вы даже не знаете, что именно разрабатываете.
Архитектура на основе микросервисов — это то, во что может превратиться проект со временем, когда вы столкнётесь с реальными проблемами.
Возможно, вы никогда не столкнётесь с этими проблемами, и многие из них можно решить иначе. Взгляните на Basecamp и Shopify. Они оба хорошо работают как монолитные приложения.
Не думаю, что кто-то назовет их маленькими, хотя они и не работают в масштабе Google.
Shopify зарабатывает $17 млн в месяц на монолите
По состоянию на середину 2018 года Shopify публично объявила, что на их платформе работает более 600 000 интернет-магазинов.
Shopify — это приложение SaaS, у которого самый дешёвый тариф составляет $29 в месяц, и у меня такое ощущение, что многие компании выбирают тариф $79 в месяц. В любом случае, даже если 600 000 клиентов использовали самый дешёвый план за $29, это доход $17,4 млн в месяц только от SaaS-направления их бизнеса.
Приложение Basecamp — другое большое монолитное приложение. Что интересно в Basecamp, так это то, что у них всего около 50 сотрудников, и только часть из них — разработчики программного обеспечения, работающие над основным продуктом.
Я хочу сказать, что можно зайти ОЧЕНЬ далеко, не спускаясь в кроличью нору микросервисов. Не создавайте микросервисы просто так.
Когда следует использовать микросервисы?
Всё зависит только от вашего решения. Это как раз одна из тех вещей, где вы не будете гуглить «микросервисы против монолита». Если вам реально нужны микросервисы, вы уже будете знать об этом.
Но может быть ситуация, что у вас куча разработчиков, которые лучше всего подходят для работы над отдельными частями приложения. Наличие десятков команд, работающих над различными компонентами продукта в изоляции — одна из разумных причин использования для микросервисов.
Имейте в виду, что если у вас маленькая команда, которая медленно растёт с течением времени, то можно начать с одного или двух микросервисов. В такой ситуации, наверное, не стоит разбивать монолит сразу на 100 микросервисов, стартуя с места в карьер.
Стоит ли овчинка выделки?
Стоит также упомянуть, что переход на микросервисы сопровождается своим собственным набором проблем. Вы меняете одни проблемы на другие, поэтому нужно взвесить плюсы и минусы, стоит ли овчинка выделки конкретно для вашего проекта.
Одна из главных проблем — мониторинг. Внезапно у вас появляется куча сервисов, которые могут быть написаны на разных технологических стеках, работать на нескольких машинах — и вам нужен способ детально их отслеживать.
Это сложная задача, потому что в идеале хотелось бы, чтобы все микросервисы использовали единую службу мониторинга.
Вероятно, вы не хотите разрабатывать собственный инструментарий, потому что это само по себе может превратиться в полноценную работу. Вот причина успеха таких компаний, как LightStep. Это один из самых интересных сервисов мониторинга, которые мне попадались.
Их продукт больше ориентирован на крупномасштабные приложения (понятно почему), но также работает и для небольших проектов. Я недавно услышал о них, потому что они были представлены на Cloud Field Day 4.
В любом случае, мониторинг — только одна из многих трудностей, но я решил упомянуть о ней, потому что это одна из самых болезненных проблем.
Заключительные мысли
В основном, я написал эту статью по двум причинам:
Во-первых, две недели назад я посетил Cloud Field Day 4 и случайно поучаствовал в групповом подкасте на смежную тему. Он должно выйти через несколько месяцев, но здесь я хотел подробнее остановиться на некоторых моментах.
Во-вторых, как автор онлайн-курсов, я получаю много вопросов о том, как создавать свои приложения.
Многие разработчики «зависают», пытаясь разбить свои приложения на изолированные сервисы ещё до того, как написали первую строчку кода. Доходит до того, что они с самого начала пытаются использовать несколько баз данных для компонентов приложения.
Этот момент мешает им двигаться вперёд, и как коллега-разработчик я знаю, насколько тяжело застрять в нерешительности (у меня такое было!).
Кстати, в настоящее время я работаю над довольно большим SaaS-приложением — платформой для размещения пользовательских курсов. Прямо сейчас над проектом работаю я один, и вы можете быть уверены, что я просто открыл редактор и начал писать код в первый же день.
Я собираюсь сохранить проект как совершенно монолитное приложение, пока не появится смысл внедрить микросервисы, но чутьё подсказывает, что такой момент никогда не наступит.
Что вы думаете об этом? Дайте знать в комментариях.