Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
На дворе 2020 год, эпоха технологических стартапов и сурового энтерпрайза. На первый взгляд, ничего общего у них нет, кроме моды на построение IT систем в стиле микросервисов. Ранее для энтерпрайза считалось стандартом использовать монолитные системы. Теперь в листингах вакансий крупных компаний чаще указывают обязанности типа «распилить на микросервисы».
Появляется ощущение, что микросервисы часто позиционируются как «серебрянная пуля» на замену монолиту. Но не всем нравится подобный подход. По факту используется он иногда некорректно или нецелесообразно. Ниже собраны примеры проблем, с которыми мне «повезло» столкнуться при использовании микросервисов в разных компаниях и которые не хочется повторять в будущем.
Жирный плюс микросервисного подхода — масштабируемость. Бесконечно большой поток пользователей и высокая нагрузка считаются неизбежными. Из-за этого тратится большое количество времени на предварительную оптимизацию, а не полезные бизнес-фичи. В действительности высокая нагрузка присутствуют далеко не всегда.
Первой жертвой предварительной оптимизации становится линейный бизнес-процесс. Он декомпозируется на множество микросервисов. Этакий запас на будущее из соображений разделения ответственностей или призрачного масштабирования. Как результат, бизнесу становится тяжелее ориентироваться в IT ландшафте и говорить на одном языке с IT, не говоря о проблемах навигации по исходному коду для самих разработчиков.
Полученные сервисы раскидываются из монорепы по отдельным репозиториям. Сами сервисы становится тяжелее связать между собой. В таком случае версия API микросервиса может начать расходится с версией этого же API в микросервисах-клиентах. Тогда старый добрый JSON заменяется на Protobuf, а HTTP на gRPC с целью получить производительность, типизацию и удобное версионирование API.
К сожалению, решения типа gRPC + Protobuf не гарантируют отсутствия ошибок. Сервисы могут последовательно падать из-за пропагации ошибки и известного несоответствия пары вход-выход сервиса. Кодовая база становится больше, отладка сервисов значительно сложнее, чем с plaintext данными, принося с собой новый ворох проблем.
Эта проблема должна решаться нормальным процессом тестирования. В частности, интеграционными тестами. Но интеграционные тесты нужно писать и прогонять для каждого микросервиса и их группы в рамках бизнес-процесса. Это достаточно сложная задача, на которую обычно не хотят выделять дополнительное время. При этом интеграционный тест микросервиса можно свести к виду модульного теста для монолита.
При всем этом привычные для монолита ограничения кочуют в микросервисы. Яркие примеры: один язык программирования и одна БД на все микросервисы. В первом случае это бывшее ограничение монолита, во втором — наследие, стремящееся стать «бутылочным горлышком» всей системы. Из-за непринятия разработчиками и менеджментом возможности существования гетерогенной системы, построенной на разных языках программирования, теряется возможность выбора подходящих инструментов для решения актуальных задач.
Кроме указанного, отдельные микросервисы могут не иметь ответственных за них разработчиков. Все начинают поддерживать все, никто не ответственнен ни за что. В таком случае знанием о работе отдельных сервисов не обладает никто, кроме последнего человека, изменявшего их код. Происходит рассинхронизация разработчиков, потеря понимания сути работы микросервисов по отношению к задачам, решаемым в рамках предметной области.
Поддерживать микросервисы сложнее, чем монолит. Инфраструктура, бывшая парой серверов, становится маленьким частным облаком. Поддержка разработчиками подобных решений занимает большое количество времени и создает проблемы для менеджмента в перспективе. Появляется надуманная необходимость дополнительной бюрократии. Нанимаются отдельные сотрудники, создаются отдельные процессы.
В таких случаях для поддержания целостности контура микросервисов могут выставлятся наборы правил работы с микросервисами. Наихудший случай — отрицание даже возможности прогона одноразового скрипта или миграции, не допуская прямого доступа в контур. Итог — скрипт оформляется как полноценный сервис, добавляя еще одну строку в длинный список микросервисов.
Получается система, которая имеет в разы больше шума, чем полезного сигнала. Везде — от инфраструктуры и до кода конкретного сервиса. От понимая схемы взаимодействия сервисов разработчиком и до менеджмента компании. Программисты невольно становятся мастерами разгадывания пазлов.
Конечно, классический монолит ничем не лучше. Он медленный, хранит у себя состояние, тяжело перерабатываем, не покрыт ни модульными, ни интеграционными тестами и т.д. Но мы можем лучше! Благодаря моде на микросервисы среди множества других плюсов мы увидели подъем CI/CD и поработали над тестированием. Теперь мы можем применять их и к другим подходам, а не только к микросервисам.
В следующий раз, когда Вы будете разрабатывать новую систему или перерабатывать старую, какого бы размера она не была, задумайтесь. Нужна ли компании масштабируемость? Нужна ли возможность справляться с высокой нагрузкой? Готовы ли Вы сами по-настоящему к микросервисам? Или лучше начать работу на основе более консервативных архитектур?
Может, не строить ракету, а построить простой самокат, ведь добраться надо только до конца улицы?
Появляется ощущение, что микросервисы часто позиционируются как «серебрянная пуля» на замену монолиту. Но не всем нравится подобный подход. По факту используется он иногда некорректно или нецелесообразно. Ниже собраны примеры проблем, с которыми мне «повезло» столкнуться при использовании микросервисов в разных компаниях и которые не хочется повторять в будущем.
Призрачная масштабируемость
Жирный плюс микросервисного подхода — масштабируемость. Бесконечно большой поток пользователей и высокая нагрузка считаются неизбежными. Из-за этого тратится большое количество времени на предварительную оптимизацию, а не полезные бизнес-фичи. В действительности высокая нагрузка присутствуют далеко не всегда.
Первой жертвой предварительной оптимизации становится линейный бизнес-процесс. Он декомпозируется на множество микросервисов. Этакий запас на будущее из соображений разделения ответственностей или призрачного масштабирования. Как результат, бизнесу становится тяжелее ориентироваться в IT ландшафте и говорить на одном языке с IT, не говоря о проблемах навигации по исходному коду для самих разработчиков.
Проблемы взаимодействия сервисов
Полученные сервисы раскидываются из монорепы по отдельным репозиториям. Сами сервисы становится тяжелее связать между собой. В таком случае версия API микросервиса может начать расходится с версией этого же API в микросервисах-клиентах. Тогда старый добрый JSON заменяется на Protobuf, а HTTP на gRPC с целью получить производительность, типизацию и удобное версионирование API.
К сожалению, решения типа gRPC + Protobuf не гарантируют отсутствия ошибок. Сервисы могут последовательно падать из-за пропагации ошибки и известного несоответствия пары вход-выход сервиса. Кодовая база становится больше, отладка сервисов значительно сложнее, чем с plaintext данными, принося с собой новый ворох проблем.
Эта проблема должна решаться нормальным процессом тестирования. В частности, интеграционными тестами. Но интеграционные тесты нужно писать и прогонять для каждого микросервиса и их группы в рамках бизнес-процесса. Это достаточно сложная задача, на которую обычно не хотят выделять дополнительное время. При этом интеграционный тест микросервиса можно свести к виду модульного теста для монолита.
Старые ограничения и привычки
При всем этом привычные для монолита ограничения кочуют в микросервисы. Яркие примеры: один язык программирования и одна БД на все микросервисы. В первом случае это бывшее ограничение монолита, во втором — наследие, стремящееся стать «бутылочным горлышком» всей системы. Из-за непринятия разработчиками и менеджментом возможности существования гетерогенной системы, построенной на разных языках программирования, теряется возможность выбора подходящих инструментов для решения актуальных задач.
Кроме указанного, отдельные микросервисы могут не иметь ответственных за них разработчиков. Все начинают поддерживать все, никто не ответственнен ни за что. В таком случае знанием о работе отдельных сервисов не обладает никто, кроме последнего человека, изменявшего их код. Происходит рассинхронизация разработчиков, потеря понимания сути работы микросервисов по отношению к задачам, решаемым в рамках предметной области.
Инфраструктурная бюрократия
Поддерживать микросервисы сложнее, чем монолит. Инфраструктура, бывшая парой серверов, становится маленьким частным облаком. Поддержка разработчиками подобных решений занимает большое количество времени и создает проблемы для менеджмента в перспективе. Появляется надуманная необходимость дополнительной бюрократии. Нанимаются отдельные сотрудники, создаются отдельные процессы.
В таких случаях для поддержания целостности контура микросервисов могут выставлятся наборы правил работы с микросервисами. Наихудший случай — отрицание даже возможности прогона одноразового скрипта или миграции, не допуская прямого доступа в контур. Итог — скрипт оформляется как полноценный сервис, добавляя еще одну строку в длинный список микросервисов.
Будущее
Получается система, которая имеет в разы больше шума, чем полезного сигнала. Везде — от инфраструктуры и до кода конкретного сервиса. От понимая схемы взаимодействия сервисов разработчиком и до менеджмента компании. Программисты невольно становятся мастерами разгадывания пазлов.
Конечно, классический монолит ничем не лучше. Он медленный, хранит у себя состояние, тяжело перерабатываем, не покрыт ни модульными, ни интеграционными тестами и т.д. Но мы можем лучше! Благодаря моде на микросервисы среди множества других плюсов мы увидели подъем CI/CD и поработали над тестированием. Теперь мы можем применять их и к другим подходам, а не только к микросервисам.
В следующий раз, когда Вы будете разрабатывать новую систему или перерабатывать старую, какого бы размера она не была, задумайтесь. Нужна ли компании масштабируемость? Нужна ли возможность справляться с высокой нагрузкой? Готовы ли Вы сами по-настоящему к микросервисам? Или лучше начать работу на основе более консервативных архитектур?
Может, не строить ракету, а построить простой самокат, ведь добраться надо только до конца улицы?