К содержимому

разделение монолита

Разделение монолита: первый сервис наружу за 20 дней

Одиннадцать лет коммитов в одном деплое, четыреста таблиц в одной схеме, релизный поезд раз в квартал. Мы находим, где данные на самом деле расходятся, сначала делим схему и вырезаем сервис, который собирается, деплоится и будит дежурного сам по себе. Rails, Django, Spring, .NET, PHP или Go: метод один и тот же, а второй сервис идёт быстрее, потому что трудная часть уже позади.

Получить оценкуПять полей. Инженер возвращается с тем, где швы, скорее всего, проходят.

20 дней на первый сервис, второй быстрее


Два сервиса и библиотека. Число сервисов должно совпадать с числом команд, готовых носить по ним пейджер.

Один деплой

Один репозиторий, одна схема, один релизный поезд, импорты, которые ходят по кругу.

  • one deployable11 years of commits
  • shared schema400+ tables
  • release trainquarterly
  • circular importscycles

Разделено

Два сервиса со своими схемами, библиотека под общее, отдельные выкатки.

  • billingGo · own schema
  • catalogueGo · own schema
  • shared kernellibrary
  • deploysper service

20 дней на первый сервис, второй быстрее

Два сервиса и библиотека. Число сервисов должно совпадать с числом команд, готовых носить по ним пейджер.

Как идёт работа

База разделяется до того, как поедет код. Этот порядок отличает обратимый проект от плохого года.
  1. 01дни 1–4

    Найти швы в данных

    Логи запросов показывают, какие таблицы читаются вместе в одном запросе. Границы там, что бы ни утверждала структура пакетов.

  2. 02дни 3–8

    Сначала разделить схему

    Разносим таблицы и убираем джойны через границу, пока всё ещё один деплой. Основной риск живёт здесь, и на этой стадии всё ещё обратимо.

  3. 03дни 8–15

    Вынести один сервис

    Тот, у которого меньше всего входящих зависимостей, а это редко тот, который раздражает людей сильнее прочих. Он едет за тем же интерфейсом, пока его эксплуатация не перестанет быть интересной.

  4. 04дни 14–20

    Дать ему свой пайплайн

    Свой репозиторий, своя выкатка, своё дежурство. Сервис, релизы которого всё равно приходится согласовывать с монолитом, не выиграл вам ничего, и видно это на пятнадцатый день, а не в конце.

Что делает платформа, что делает человек

Найти кандидатов в швы - это измерение, и платформа делает его по вашим же логам запросов. Выбрать между ними - вопрос того, кто чем владеет, и здесь инженер садится с вашими лидами.
Шов выбран верно, если после выноса большинство правок трогают только одну сторону.
Что делает платформа, что делает человекКто делаетПримечания
Строит карту совместного доступа к таблицам и связности модулейПлатформаПо логам запросов и графу вызовов, за период, который включает закрытие месяца.
Предлагает швыВместеПлатформа ранжирует кандидатов. Человек сверяет их с границами ваших команд.
Ломает джойны через границуПлатформаМеханическая работа, читается пул-реквестами, едет мелкими кусками.
Выбирает, какой сервис пойдёт первымИнженерВладение командой решает это чаще, чем сам код.
Границы транзакцийИнженерТам, где одна транзакция базы раньше пересекала шов, кто-то должен решить, что происходит при отказе.
CI, выкатка и дежурствоВместеСервис без своего пайплайна и своей смены - это модуль с лишними сетевыми хопами.

Кто режет шов

Десятки миграций, больше десяти лет на системах, которые строили давно ушедшие люди, и достаточно разделений, чтобы знать, какие из них окупаются. Монолиты на Rails, Django, Spring, .NET, PHP и Go, схемы на четыреста таблиц и десятилетие джойнов через границу. Шов никогда не проходит там, где его рисует архитектурная схема, и найти настоящий - это и есть большая часть того, что вы покупаете.


Проверкой служит первый вынос, и он ограничен: один сервис, своя схема, своя выкатка, в проде. Рабочий ответ ценой одной фазы.

Вопросы, которые задают инженеры

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

Начните с одного выноса

Достаточно размера монолита, частоты релизов и того, что толкает к изменениям. Вернёмся с тем, где швы, похоже, проходят, и во что обойдётся первый сервис.

Получить оценку

Отвечает инженер, и первый вопрос обычно про частоту релизов.