Большинство корпоративных систем в банках, страховых и ведомствах построены как монолит: единая кодовая база, общая база данных, развёртывание целиком. Пока пользователей сотни, а транзакций – десятки тысяч в сутки, это работает и обходится дёшево. Проблемы начинаются, когда нагрузка растёт быстрее, чем железо под ней. Менеджеры просят «добавить серверов», а время отклика всё равно ползёт вверх. Разберём, где именно монолит упирается в потолок и что с этим делать без полной переделки.
Вертикальное масштабирование заканчивается первым
Стандартная реакция на рост нагрузки – поставить машину помощнее: больше ядер, больше памяти, быстрее диски. Это вертикальное масштабирование, и у него жёсткие пределы. Во-первых, цена за каждый следующий процент производительности растёт нелинейно: топовый сервер стоит непропорционально дороже двух средних. Во-вторых, монолит часто не умеет использовать все ядра – узкое место смещается в блокировки общей БД, и новые ядра простаивают.
Реальный предел почти всегда упирается в базу данных. Один экземпляр СУБД обслуживает запись и чтение для всего приложения. Когда счётчик блокировок и ожиданий растёт, добавление CPU на сервер приложений уже ничего не даёт – очередь стоит на уровне хранилища. Здесь стоит честно измерить, что именно тормозит, а не наращивать ресурсы вслепую.
Что выносят из монолита в первую очередь
Полный переход на распределённую архитектуру для работающей системы – риск, который госзаказчик редко принимает. Но из монолита можно аккуратно вынести самые нагруженные части, не трогая ядро.
- Чтение и аналитику. Отчёты и витрины не должны конкурировать за блокировки с оперативными транзакциями. Их выносят на реплику или в отдельное аналитическое хранилище – это естественный мост к построению полноценной аналитики на больших объёмах данных.
- Интеграционный слой. Обмен с внешними системами и СМЭВ выносят в отдельную шину, чтобы пиковый трафик интеграции не ронял основной контур.
- Каналы доступа. Веб- и мобильные клиенты обслуживают через прослойку с кэшированием. Когда мобильный доступ становится сценарием по умолчанию, эта прослойка снимает с ядра основную часть запросов на чтение.
Каждый такой вынос – это горизонтальное масштабирование отдельного компонента: его экземпляры размножают за балансировщиком независимо от остального монолита.
Кэширование и состояние
Главный враг масштабирования – состояние, которое держится на одном узле. Если сессия пользователя или прикладной кэш привязаны к конкретному серверу приложений, добавить ещё один узел нельзя без липких сессий и боли с отказоустойчивостью. Решение – выносить состояние во внешний слой: распределённый кэш и общее хранилище сессий. Тогда серверы приложений становятся взаимозаменяемыми, и горизонтальное масштабирование работает по-настоящему.
Тот же принцип касается управления устройствами и доступом: чем больше клиентов, тем важнее централизованный контроль политик, как мы разбирали в материале про управление мобильным парком. Состояние и политики должны жить в одном управляемом месте, а не размазываться по узлам.
Вывод
Монолит не нужно ломать при первых признаках нагрузки. Сначала измеряют узкое место, выносят чтение и интеграцию, отделяют состояние от узлов приложения и этого хватает на годы роста. К распределённой архитектуре переходят осознанно, когда бизнес-задача того требует, а не из моды. Развитие нагруженной корпоративной системы – это проектирование масштабирования в составе бизнес-систем без остановки эксплуатации.