Как избежать 7 критических ошибок при переходе на микросервисы

Страницы:  1

Ответить
 

Professor Seleznov


Всем привет, меня зовут Сергей Прощаев. Я Tech Lead и руководитель направления Java | Kotlin разработки в FinTech и E-commerce. За последние годы прошёл через несколько миграций монолита на микросервисы — где-то консультировал, где-то участвовал руками. И почти всегда наблюдал одну и ту же картину: команда мигрирует, ожидает облегчения, а получает боль, которой не планировала. В этой статье разберу ошибки, которые чаще всего к этой проблеме и приводят.
Вот сценарий, который я видел не раз. Стартап вырос человек до пятидесяти разработчиков. Монолит на Python или Node.js начал тормозить — что-то на восемьсот тысяч строк кода, который никто целиком уже не держит в голове. Каждый день мерж-конфликты. Деплой стал стрессом для всей команды — выкатываем по пятницам, на всякий случай. Кто-то на ретро вспоминает доклад с конференции про Netflix, кто-то кидает в чат статью про микросервисы. И всё. На следующей планёрке как-то само собой произносится: «Слушайте, давайте уже на микросервисы. Это решит все проблемы».
Три месяца спустя команда едет медленнее, чем ехала на монолите. Разработчик меняет код в Service A и ломает Service B — узнаёт об этом не на ревью, а от пользователей в продакшене. Между сервисами образовалась дикая паутина синхронных запросов. Раз в неделю — ночной звонок, потому что алерт либо не сработал, либо сработал, но никто не понял, в каком сервисе корень проблемы. Логи рассыпаны по пяти разным местам, и чтобы собрать картинку одного запроса, нужно полчаса. А монолит, который ругали, в эти моменты вспоминается как рай.
Проблема не в микросервисах. Проблема в том, что границы между ними выбирали неправильно. Давайте разберём 7 ошибок, которые обычно к этому приводят.
pic
Рис. 1. Архитектурный выбор: монолит vs микросервисы
Ошибка 1: Микросервисы из-за моды, а не из-за боли
Симптом: Переход на микросервисы начался с мечтаний, а не с анализа реальных проблем. Я слышал это на разных проектах раз пять, наверное: «У Netflix микросервисы», «это scalable», «это современно», «нам пора расти». Аргументы про конкретную боль монолита при этом не звучат — потому что их в нужном виде ещё никто не сформулировал.
Почему так происходит: Микросервисы — это хорошо звучащее слово. Про них пишут статьи на Хабре, про них рассказывают спикеры на JPoint и Highload. Я и сам с удовольствием смотрю эти доклады. Но боль, которую микросервисы реально лечат, — она очень узкая: команды толкаются локтями в одном репозитории, деплой одного куска ломает другой, разные части системы хотят сильно разной нагрузки. Если у вас из этого ничего нет — микросервисы вам не нужны.
Что это ломает: Если у тебя нет этих проблем, микросервисная архитектура просто усложнит жизнь. Вместо одной проблемы (медленный монолит) получишь три: консистентность данных, сетевая задержка и операционная сложность.
Как исправить: Прежде чем начинать архитектурный refactor, ответь на вопросы:
  • Где именно сейчас узкое место? (память? CPU? I/O?)
  • Какие команды мешают друг другу при разработке?
  • В каких частях системы требования к нагрузке сильно отличаются?
  • Сколько человеко-часов уходит сейчас на координацию между командами?
Если ответы размытые — не спеши на микросервисы. Правильный путь архитектурной эволюции:
  • Оптимизированный монолит — решить проблемы в текущей кодовой базе (кеширование, индексы, асинхрон)
  • Modular Monolith — это критически важный промежуточный шаг. Введи явные bounded contexts с независимыми модулями, четкие ownership boundaries между командами (но всё ещё одна кодовая база). Это решает проблему координации, не добавляя операционную сложность микросервисов.
  • Selective Extraction — только после этого, когда модули чётко определены, начинай выделять отдельные сервисы из проверенных модулей.
Многие команды застревают где-то между первым и вторым пунктом, потому что про modular monolith либо не слышали, либо считают его «недомикросервисами». Помню как однажды объяснял лиду продукта, почему мы не идём в микросервисы сразу: «У нас не будет команд, которые конкурируют за один репозиторий ещё минимум год. Зачем нам сейчас Kafka, Kubernetes, service mesh и пять новых ролей в DevOps?». Сошлись на modular monolith. Через полтора года часть модулей действительно стали отдельными сервисами — но уже на готовых границах, без появления каких-либо проблем.
Ошибка 2: Shared database между сервисами (неправильно выбранное время)
Симптом: Несколько микросервисов смотрят в одну общую БД. На старте кажется, что это экономия — не надо ничего синхронизировать, данные везде свежие, транзакции работают. Я сам так делал. Через год эта «экономия» превращается в архитектурный замок без ключа.
Почему так происходит: Первый рефакторинг монолита часто идёт по пути наименьшего сопротивления: берешь один слой логики, выносишь в отдельный сервис, а БД оставляешь общей. Кажется, что проблемы нет.
Что это ломает: Tight coupling возвращается, только теперь через дверь схемы БД. Помню случай: команда Service A решила переименовать поле user_email в email_address. Сделала миграцию. Service B, который читал эту же таблицу, упал в продакшене ровно через семь минут после деплоя. И ладно бы тут можно было быстро откатиться — но Service A уже успел записать данные в новой схеме. Любая миграция БД превращается в проект на три команды и две недели согласований. Это убивает ту самую независимость, ради которой шли в микросервисы.
Как исправить: Идеально — независимое владение данными. На практике это может выглядеть по-разному, зависит от этапа эволюции:
  • На начальном этапе миграции — shared database часто неизбежен как transitional architecture. Это временное решение. Но нужна дорожная карта выхода из этого состояния.
  • Способы логического разделения внутри одной БД:
    • Отдельная schema для каждого сервиса с явными access rules
    • CDC (Change Data Capture) — Service A пишет в свою таблицу, Service B читает через event stream. Общая БД, но логически независимы.
    • Transactional Outbox — Service A пишет данные и событие в одной транзакции, другие сервисы читают события асинхронно. Это гарантирует consistency без распределённых транзакций.
  • В финальном состоянии — каждый сервис должен владеть своей БД (отдельный instance). Это дает полную независимость: разные версии schema, разные СУБД если нужно, отдельный backup и recovery.
Главное — это дорожная карта. Я бы здесь поставил такой критерий: если вы можете на бумаге нарисовать, как и в какой квартал будете выходить из shared database, — это нормальный переходный этап. Если на вопрос «когда разделим?» команда мнётся — это уже архитектурный долг, и он только растёт.
Ошибка 3: Игнорирование network latency
Симптом: На дизайн-ревью архитектор показывает красивую диаграмму. Service A зовёт Service B, тот зовёт Service C. Стрелочки. Стройно. Один из моих первых проектов после миграции выглядел именно так. В продакшене эта стройная диаграмма стала превращаться в цепочку синхронных вызовов, которая на простой клиентский запрос накручивала такую задержку, что мобильное приложение начинало показывать спиннер.
Почему так происходит: В монолите функция вызывает функцию — это практически бесплатно (микросекунды, в памяти). Сеть — это совсем другой уровень стоимости. Каждый вызов платит за: serialization (например, JSON), network RTT (round trip time), connection management / TLS overhead (HTTP/2 keep-alive переиспользует соединения, но первый вызов платит за handshake), retry logic, queueing на перегруженном сервисе. Даже внутри одного data center это десятки миллисекунд дополнительной latency за один hop. А если хопов 5-7 — это становится заметно пользователю.
Что это ломает: Клик юзера, который раньше отрабатывал за 50–100 мс в монолите, в синхронной цепочке через пять сервисов начинает занимать 200–500 мс. И это в идеальных условиях. Плюс каждый hop — это самостоятельная точка отказа. Совокупная вероятность сбоя растёт с каждым добавленным синхронным зависимым. Простая арифметика: если у каждого сервиса 99.9% uptime, то пять последовательных дают примерно 99.5% — это уже минус четыре с лишним часа доступности в месяц по сравнению с одним сервисом. Я регулярно встречаю архитекторов, которые этот расчёт у себя в голове не держат.
Как исправить: При проектировании интеграций между сервисами всегда думай про latency пути:
  • Если запрос к Service B нужен Service A для ответа клиенту (синхронно в critical path) — это проблема. Либо коллапсируй эти сервисы в один, либо переведи на асинхронность.
  • Асинхронность не значит медленнее. Клиент получает ответ сразу (от Service A), а Service A сам фоном синхронизируется с другими сервисами.
  • Используй кеширование между сервисами — многие вызовы можно избежать вообще.
  • Если всё же нужны синхронные вызовы, уменьши количество хопов в пути (лучше один вызов в сервис, который знает про других, чем цепочка).
Ошибка 4: Операционная сложность на потом
Симптом: В начале миграции все думали только о коде. Логирование? Сделаем потом. Трейсы между сервисами? Потом. Алерты, если упадёт Service D? Тоже потом. Я и сам так делал в первые годы — наблюдаемость казалась чем-то, что можно докрутить, когда «всё уже работает».
Почему так происходит: На старте просто нет времени, всем хочется побыстрее показать первую работающую микросервисную фичу — она же красивая и презентуемая. А операционка выглядит как скучная инфраструктура, которой можно заняться «когда выдохнем». Только выдохнуть не получается ровно по той причине, что без неё первый же серьёзный инцидент бьёт сильнее любой фичи.
Что это ломает: Первый серьёзный инцидент становится кошмаром. Помню как однажды разбирал инцидент в три ночи: Service A упал, алерт прилетел, но прилетел такой, что непонятно — это причина или следствие. Логи в одном сервисе показывают тайм-аут, в другом — пустоту, в третьем вообще нет логов за этот промежуток, потому что их забыли подключить к централизованному хранилищу. Чтобы собрать картинку одного запроса, мы вшестером сидели в зуме два с половиной часа. Distributed tracing? Не настроен. Trace ID? Где-то есть, но не пробрасывается. С таким набором инструментов любой инцидент превращается в гадание на кофейной гуще — и неизвестно, успеешь ли ты разобраться до утра.
Как исправить: Distributed tracing (Jaeger, Datadog, New Relic) — для меня это не опция, а требование на день первый. Централизованное логирование (ELK, Splunk) — туда же. Алерты строятся на SLI, а не на технических метриках: не «CPU выше 80%», а «error rate на эндпоинте регистрации выше 1%». Разница в том, что первое — это про железо, а второе — про то, что реально чувствует пользователь. И всё это нужно настраивать в самом начале миграции, а не «когда дойдут руки» — потому что не дойдут.
Ошибка 5: Слишком мелкая декомпозиция
Симптом: Каждый кусок бизнес-логики выделен в отдельный микросервис. Видел проект, где было: Users, Orders, OrderItems, OrderStatuses, Payments, Refunds, Notifications, Audit, плюс ещё пара технических сервисов. Девять штук на средний по нагрузке маркетплейс. На белой доске всё выглядело логично и аккуратно. В реальности это был зоопарк, где сотрудники одной команды не знали в лицо сервисы соседней.
Почему так происходит: Команды часто берут принцип Single Responsibility и применяют его буквально: один сервис — одна ответственность. Звучит логично. Но «одна ответственность» — это размытое понятие, и его легко прочитать как «одна таблица» или «один CRUD». Так и появляются OrderItems Service и OrderStatus Service, которые сами по себе никакой бизнес-задачи не решают.
Что это ломает: Дикий граф зависимостей. Service A нужны данные от B и C, B берёт их у D, D ходит в Notifications, чтобы что-то логировать. Один клиентский запрос превращается в шесть RPC-вызовов. Я как-то нарисовал такую диаграмму на проекте — получилась шерсть. Половина зависимостей вообще про мелочь: какой-то сервис ждёт одного поля, чтобы построить статистику. Совокупная вероятность отказа растёт с каждой добавленной синхронной связью — и это всё нужно потом мониторить, тестировать, версионировать.
Как исправить: Ключ — декомпозировать не по техническим слоям (как часто делают), а по bounded contexts (DDD):
  • Bounded Context — это явная граница, внутри которой модель данных имеет одно значение. Например, Order для User Service — это набор контактов, а для Order Service — это финансовый документ с историей статусов.
  • Transactional Boundary — что изменяется вместе в одной транзакции. Товары в заказе изменяются вместе, поэтому Order + OrderItem должны быть в одном сервисе.
  • Ownership Boundary — какая команда владеет этим куском системы и может менять его независимо.
  • Change Cadence — что деплоится вместе. Если Order и Payment всегда менялись вместе в старой системе, возможно, они должны быть в одном сервисе и на начальном этапе.
Правильный пример: Orders Domain (не только Order, но и OrderItem, OrderStatus, Payment тоже) как один микросервис, потому что это одна бизнес-операция. Users Domain отдельно. Notifications Domain подписывается на события.
Плохой пример: Users Service, Orders Service, OrderItems Service, Payments Service, OrderStatus Service, Notifications Service — каждый на одну таблицу. Получается 6 сервисов вместо 3, граф зависимостей превращается в шерсть, а общая доступность системы падает с каждой новой синхронной связью.
Ошибка 6: Неправильный выбор консистентности и интеграции
Симптом: User зарегистрировался. Эти данные нужны в трёх местах: User Service хранит профиль, Notification Service отправляет приветственное письмо, Analytics Service логирует событие для метрик. На дизайне всё просто: «возьмём Kafka, добавим Event Sourcing, может быть, Saga — и поехали». Через три месяца в продакшене я смотрел в дашборд и видел: примерно у двух процентов пользователей не приходит приветственное письмо. У Analytics — расхождение с базой User Service на полтора процента. В логах — race conditions, которые сложно даже сформулировать.
Почему так происходит: Я часто вижу, как команды смешивают разные уровни абстракции. Это похоже на то, как если бы кто-то сказал: «выбери между автомобилем, левым поворотом и красной краской». Все три слова про машины и дороги, но они отвечают на разные вопросы. С Kafka, Saga и Event Sourcing та же история:
  • RabbitMQ, Kafka — это ТРАНСПОРТ (как доставить сообщение)
  • Saga Pattern — это КООРДИНИРУЮЩИЙ ПАТТЕРН (как обработать распределённую транзакцию)
  • Event Sourcing — это МОДЕЛЬ ХРАНЕНИЯ (как сохранять историю)
Они решают разные проблемы!
Что это ломает: Без чёткого выбора consistency model система начинает протекать в разных местах. Симптомы, которые я видел вживую:
  • User регистрируется успешно, но Notification Service о нём так и не узнаёт — событие потерялось где-то в шине.
  • События приходят дважды, иногда трижды, иногда в неправильном порядке. Идемпотентность? Никто не думал.
  • Между двумя сервисами рассинхрон данных, и никто не знает, какие данные считать истинными — приходится садиться и сверять руками.
  • DLQ копит сообщения месяцами, в неё никто не заглядывает. Когда заглянули — там тысячи писем, которые надо было отправить год назад.
  • Retry logic без идемпотентности создаёт дубликаты. Пользователь получает одно и то же письмо три раза и пишет в поддержку.
Как исправить: Это сложный раздел, требует системного подхода:
Шаг 1: Определи, где нужна строгая консистентность
Не везде нужна eventual consistency. Задай вопросы:
  • Где нужна ACID? (транзакции в одном сервисе, например: при создании Order нужна одна atomic операция для Order + OrderItems)
  • Где допустима eventual consistency? (Notification может прийти с задержкой в 30 секунд, это ок)
Шаг 2: Выбери integration pattern для каждого случая
Для sync критических путей:
  • Колапс микросервисов (если Service A и B всегда нужны вместе — они должны быть одним сервисом)
  • Синхронный RPC (gRPC, REST) с таймаутами и circuitbreaker
Для async non-critical:
  • Asynchronous Messaging (RabbitMQ, Kafka) + хорошая обработка errors
  • Transactional Outbox Pattern — Service A пишет в свою таблицу (User) и в таблицу outbox в одной ACID-транзакции. Отдельный worker вычитывает outbox и публикует события. Гарантия: ни одно событие не потеряется, даже если упадет сервис.
  • CDC (Change Data Capture) — база сама публикует изменения через Debezium или аналог
Для распределённых транзакций:
  • Saga Orchestration (одна служба оркестрирует: "сначала создай Order, если success то деньги, если fail то rollback")
  • Saga Choreography (сервисы реагируют на события друг друга: OrderService опубликовал OrderCreated, PaymentService подписан и начинает платеж)
Шаг 3: Обязательные инструменты (без них система ломается)
  • Idempotency Keys — каждый запрос имеет уникальный ID. Если notification будет обработан дважды, второй раз будет игнорироваться.
  • Retry Logic с exponential backoff — если Notification упал, повтори через 1s, потом 2s, потом 4s. Но не бесконечно.
  • DLQ (Dead Letter Queue) — если сообщение упало 5 раз, его нужно отправить в DLQ для ручного анализа.
  • End-to-End Exactly-Once Processing — практически недостижим. Kafka имеет EOS (Exactly-Once Semantics) и transactional messaging, но это работает в пределах одной системы. End-to-end exactly-once processing в распределённых системах (когда данные пересекают boundaries разных сервисов и хранилищ) практически невозможен. На практике системы проектируют вокруг at-least-once delivery + idempotent processing (каждый consumer должен безопасно обрабатывать дубликаты).
  • Poison Messages Detection — если одно сообщение ломает систему, найди его и изолируй.
  • Schema Evolution — если Event структура изменилась, старые consumer-ы должны её понимать.
Пример: правильно спроектированная синхронизация
User регистрируется:
  • UserService пишет User в БД и Event в outbox таблицу (одна транзакция)
  • Outbox Worker читает Event и публикует в Kafka с idempotency key
  • NotificationService подписан на UserCreated
  • NotificationService получает событие, проверяет idempotency key
    • Если это первый раз: отправляет письмо, сохраняет event_id как processed
    • Если видели раньше: игнорирует (идемпотентно)
  • Если Notification упал, retry через несколько секунд
  • Если 5 раз не отправилось, письмо идет в DLQ
Это надежная система.
Ошибка 7: Недооценка затрат на миграцию
Симптом: Слышал этот диалог раз десять. Менеджер спрашивает: «Когда будет готово?». Разработчик отвечает: «Ну, недели две». Через месяц — всё ещё не готово. Не потому что команда плохо кодит, а потому что в эти «две недели» никто не заложил инфраструктуру, миграции данных, обучение, обкатку и обратный путь, если что-то пойдёт не так.
Почему так происходит: Со стороны миграция с монолита выглядит как обычная фича — «выделим кусок, обернём в сервис, поднимем». Но это не одна задача, это десятки мелких решений, которые на этапе оценки никто не видит. Как поднимать БД каждого сервиса? Как ротировать логи? Как настраивать CI/CD pipeline под новый сервис? Как откатываться, если что-то сломалось? Каждый из этих вопросов — отдельный день работы, а иногда и неделя. Складываешь их вместе — и «две недели» превращаются в три месяца.
Что это ломает: Проект уходит в срыв. Сроки сдвигаются — сначала на месяц, потом ещё на квартал. Команда выгорает: люди работают вечерами, потому что днём «надо ещё фичи делать в монолите». Качество кода падает — торопимся, ревью становится формальным. И самое неприятное — внутри команды возникает ощущение, что миграция была плохой идеей. Хотя дело не в миграции, а в том, что её заложили в план как двухнедельную задачу.
Как исправить: Миграция с монолита на микросервисы редко бывает проектом на несколько недель. Для крупных систем это часто многоквартальная или даже многолетняя эволюция. Вот почему:
  • Strangler Pattern — ты не переписываешь всё за раз. Ты постепенно выделяешь куски монолита (strangling его). API Gateway направляет старые запросы в монолит, новые — в микросервис. Это может занять месяцы.
  • Coexistence Phase — долгое время монолит и микросервисы живут рядом. Это значит:
    • Dual-write periods (пишешь в обе системы одновременно)
    • Anti-corruption layers (защита от несовместимости данных)
    • Параллельное тестирование в обеих системах
  • Инфраструктура:
    • БД для каждого сервиса (миграция данных без потерь)
    • Сети, API Gateway, service discovery
    • CI/CD пайплайн для каждого сервиса
    • Мониторинг и логирование (OpenTelemetry setup)
  • Обучение команды — это может быть недооценено. Микросервисный mindset отличается от монолитного:
    • Думать про распределённые транзакции вместо ACID
    • Eventual consistency вместо strong consistency
    • Ownership разных команд над разными сервисами
Реалистичные сроки:
  • Для стартапа с 50 разработчиков и системой 1-2 года: 2-4 месяца для первых пилотных микросервисов
  • Для зрелой системы с 500K+ строк кода: 6+ месяцев на первый сервис, потом год+ на остальное
  • Для финтех-системы с критичными требованиями: 1-2 года на полную миграцию
Главное — поменять оптику. Я бы предпочёл, чтобы команда смотрела на миграцию не как на проект с датой завершения, а как на постепенную архитектурную эволюцию. С промежуточными состояниями, в которых система живёт месяцами и никому не стыдно, что «мы ещё не закончили». Закончить миграцию по-настоящему получается только у тех, кто не считает её гонкой.
Правильные границы между сервисами
Вот как выглядит правильная декомпозиция (рис. 2). Заметь: сервисы независимы по данным, но связаны event-driven интеграцией.
pic
Рис. 2. Правильная архитектура микросервисов
Что важно увидеть на этой схеме: Order Service и User Service полностью независимы. У каждого своя БД, и они не вызывают друг друга напрямую. Если в Order Service происходит что-то существенное, он публикует событие в общую шину. Кому это событие нужно — Notification, Analytics — те подписаны и обрабатывают его у себя, идемпотентно (то есть повторный приход того же события не сломает данные). API Gateway стоит впереди, чтобы клиент не знал внутреннюю топологию и попадал на нужный сервис через единую точку входа.
Основная мысль: сервисы связаны не вызовами, а событиями. Если упадёт Notification, заказы продолжат создаваться. Если упадёт Analytics, пользователь зарегистрируется и получит письмо. Никаких цепочек «сломалось одно — встало всё».
Что НЕ нужно делать
А вот что часто видим на практике (рис. 3):
pic
Рис. 3. Антипаттерн: Shared Database и Tight Coupling
Что важно увидеть на этой схеме: один клиентский запрос — это цепочка синхронных вызовов, проходящая через три сервиса по очереди (Order - User - Notification и обратно). Все три сервиса смотрят в одну и ту же базу данных. Стоит изменить схему таблицы users — и Order Service ломается на ближайшем деплое. Стоит упасть Notification — клиент не получит ответ на свой запрос, потому что Order ждёт цепочку до конца.
Основная мысль: это не микросервисы. Это распределённый монолит — со всеми минусами монолита (общая БД, жёсткие связи), плюс новые минусы распределённой системы (сетевые задержки, операционная сложность). Худшее из обоих миров. Так делать не надо никогда — даже на переходном этапе.
Чек-лист перед миграцией на микросервисы
Перед тем, как начинать, проверь себя:
  • Ты чётко обозначил боль в монолите (не просто "хочется микросервисов")
  • Каждый микросервис имеет собственную БД (нет shared database)
  • Между сервисами асинхронная интеграция (Kafka, RabbitMQ, очереди)
  • Учтены сетевые задержки при проектировании (нет глубоких цепочек вызовов)
  • Настроено distributed tracing (Jaeger, DataDog или аналог)
  • Настроено централизованное логирование
  • Есть strategy для eventual consistency (saga, event sourcing или другое)
  • Реалистичные оценки на миграцию (минимум 2-3 месяца серьёзной работы)
  • Команда обучена микросервисному mindset (не просто закинули код в разные Docker контейнеры)
  • Есть rollback plan на случай, если всё сломается
Если хотя бы один пункт в списке пока не готов — не спеши с миграцией. Лучше подготовься сейчас, чем разбираться потом в 3 ночи.
Таблица ошибок и как их выявить
Ошибка Симптом в продакшене Как проверить
Неправильная причина миграции Система заработала медленнее, чем была Метрики: p95 latency, throughput, инцидент rate
Shared Database Миграция одного сервиса ломает другой DB schema change требует координации между 3+ сервисами
Network Latency Клиентские запросы медленнее, чем в монолите В critical path есть множество synchronous хопов; каждый hop может быть точка отказа
Нет мониторинга Инцидент в 3 ночи, не знаешь, что произошло Нет distributed trace для запроса, нет алертов на SLI
Мелкая декомпозиция Частые сбои, потому что зависит от множества сервисов Service dependency graph показывает 10+ зависимостей на один сервис
Нет стратегии consistency Рассинхрон данные, потребители получают неполную информацию Есть события, которые приходят не всем потребителям, или приходят в неправильном порядке
Недооценка миграции Проект срывает дедлайны месяц за месяцем Burning hours на infrastructure & DevOps, а не на features

Вывод: Это не просто архитектурное решение
Ошибки в границах микросервисов — это не строчка в графе «технический долг». Это бессонные ночи дежурного, это код, который через год придётся переписывать, это люди, которые выгорают. Микросервисы — не лекарство «для всех» и не «прямо сейчас».
Но если выбрать их правильно — когда есть реальная боль монолита, когда границы понятны, когда инфраструктура готова — они действительно дают свободу. Команды перестают толкаться в одном репозитории. Сервисы катятся независимо. Узкое горло монолита исчезает.
Главный навык здесь, как мне кажется, — не в коде и не в знании конкретных фреймворков. Это архитектурное мышление: умение увидеть, где проходит граница между доменами, где синхронная интеграция тебя убьёт, где нужен event-driven подход. Это то, что отделяет джуниора-архитектора от опытного. И этому, к сожалению, нельзя научиться по одной статье — но можно начать смотреть в правильную сторону.-Микросервисы редко ломаются из-за самого факта перехода. Чаще проблемы начинаются на границах сервисов, в интеграциях, авторизации, очередях и консистентности данных. Эти темы удобнее разбирать на живых примерах — приходите на бесплатные уроки, где можно познакомиться с экспертами, посмотреть формат обучения и задать свои вопросы.
  • 1 июня в 20:00. «Практика аутентификации и авторизации в микросервисной архитектуре». Записаться
  • 16 июня в 20:00. «Использование брокера сообщений Apache Kafka в распределенных очередях». Записаться
Чтобы оставаться в курсе всех бесплатных мероприятий, подписывайтесь на канал OTUS в Max. -Источник
 
Loading...
Error