Поэтапно разгрузили ключевые контуры интернет-магазина и подготовили платформу к пиковому трафику без полной замены существующей системы. Попутно доработали несколько ключевых бизнес-фичей.
e-Commerce
PHP
Swoole
Laravel
Elasticsearch
MongoDB
PostgreSQL
Kafka
Содержание
Задача
Весной 2025 года Lime потребовалось усилить команду поддержки и развития интернет-магазина. Одной из приоритетных задач стала подготовка платформы к распродажам.
При сезонном росте трафика увеличивалось количество запросов к каталогу, корзине, геосервисам и оформлению заказа. Узкие места, почти незаметные при обычной нагрузке, в пиковые периоды крайне негативно влияли на работоспособность сайта.
Проекту была нужна команда, способная погрузиться в существующую архитектуру после прошлой команды, определить источники нагрузки и последовательно развивать платформу вместе с внутренними специалистами Lime.
Формат работы
На проекте сформировали объединённую команду Lime и Lachestry. Специалисты Lachestry вошли в существующие процессы разработки и подключились к анализу архитектуры, проектированию решений, декомпозиции задач и техническому управлению PHP-направлением.
Новые компоненты не должны были становиться «чёрным ящиком». Поэтому команда сохранила понятный для проекта технологический стек и единые эксплуатационные механики.
Подход к архитектуре
К началу работ значительная часть публичного API, каталожных запросов и интеграций проходила через Laravel-монолит и его операционную базу данных. Полная замена платформы замедлила бы развитие бизнеса и добавила миграционные риски, поэтому архитектуру меняли поэтапно.
Определяли наиболее нагруженные и достаточно автономные контуры.
Выносили их без одновременного изменения публичных API-контрактов.
Сохраняли PHP как основной язык разработки.
Переключали маршруты постепенно и оставляли бизнес-логику у её владельца.
Добавляли fallback только там, где он не создаёт риск неконсистентной записи.
Маршрут запроса зависит от сценария
Клиентская витрина
→
API Cache
Catalog Indexer
Geo Service
API Gateway
Account Facade
→
runtime / MongoDB
Elasticsearch
внешний провайдер
целевой сервис / монолит
Общая платформа для PHP-сервисов
Для новых высоконагруженных сервисов выбрали Swoole и Phalcon. Swoole работает с долгоживущими worker-процессами и coroutine-friendly I/O, а Phalcon используется как прикладной слой маршрутизации, dependency injection и модульной организации.
Общие инфраструктурные механики вынесли в переиспользуемые Composer-пакеты, чтобы каждый следующий сервис начинался с предметной границы ответственности, а не с повторной сборки платформенного слоя.
Жизненный цикл Swoole-сервера и HTTP-клиенты с пулами соединений.
Runtime-кэш и интеграции с MongoDB, Redis, PostgreSQL и Elasticsearch.
Health checks, структурированные логи, трассировка и APM.
Единая обработка заголовков, сайта, языка и контекста запроса.
API Cache: разгрузка публичного API
Повторяющиеся запросы к меню, справочникам, настройкам, секциям и другим read-heavy данным нагружали Laravel и PostgreSQL, хотя ответы менялись намного реже, чем запрашивались.
На сайте уже был применен Cloudflare-кэш, но он попадал под проблемы с РКН + не давал гибкости в настройке кэша (были частые cache misses). Поэтому был создан более настраиваемый edge-сервис с кэшированием под контролем инфраструктуры.
01 Сервис проверяет быстрый runtime-кэш внутри Swoole.
02 При отсутствии данных обращается к общему кэшу в MongoDB.
03 Если ответа нет и там, направляет запрос в монолит или целевой сервис.
04 Сохраняет ответ и возвращает его клиенту в совместимом формате.
Что хранит и контролирует сервис
В кэш попадает не только тело ответа, но и статус, необходимые заголовки, алгоритм сжатия и теги для последующей инвалидации. Для маршрутов действуют отдельные правила хранения и TTL.
Защита от одновременного пересчёта одного ключа при всплеске запросов.
Очистка по тегам, принудительное обновление и прогрев данных.
Инвалидация runtime-кэша по событиям.
Метрики попаданий и промахов для разных уровней хранения.
Проксирование части поисковых и рекомендательных сценариев.
Catalog Indexer: read model в Elasticsearch
Страницы категорий, фильтрация и получение товарных данных оставались отдельным источником нагрузки. Algolia продолжила выполнять роль поискового движка, а для каталожного чтения команда разработала отдельный сервис поверх Elasticsearch.
Catalog Indexer возвращает ответы в формате, совместимом с контрактами монолита. Благодаря этому маршруты можно переключать постепенно, не меняя весь потребляющий код одновременно.
Товары, модели, категории и варианты их представления.
Фильтры, образы, комплекты и баннеры.
Остатки, магазины, связанные и дополняющие товары.
Обновление без остановки чтения
Каталожные индексы разделены по назначению и сайту. Вместо одного большого документа используются отдельные read models для структуры раздела, товарной проекции, цен, остатков и магазинов.
01 Полный экспорт создаёт новую версию индекса и атомарно переключает alias.
02 Частичная индексация обновляет изменившиеся сущности без полного перестроения.
Geo Service: изоляция внешних провайдеров
Геопоиск используется при выборе города, улицы и дома, определении индекса и заполнении адреса доставки. Его скорость зависит от внешних API, поэтому ожидание ответа внутри монолита занимало ресурсы основного приложения.
Команда вынесла этот контур в отдельный Swoole-сервис, который выбирает провайдера по сайту и сценарию и приводит разные ответы к единому контракту.
Адаптеры для DaData, Яндекс Геокодера, Post.kz и определения страны по IP.
Нормализация адресов с учётом особенностей разных стран.
Runtime- и MongoDB-кэш повторяющихся запросов.
Отдельная очистка геокэша и наблюдаемость внешних вызовов.
API Gateway: защита критичных маршрутов
По мере появления сервисов понадобился слой для маршрутизации пользовательских запросов и управляемой реакции на перегрузку. Gateway обслуживает прежде всего пользовательские и чувствительные к повторной отправке сценарии.
Он не является обязательной точкой входа для всего API: каталожные, кэшируемые и географические route slices могут сразу попадать в соответствующие сервисы.
Проверка разрешённых маршрутов и HTTP-методов.
Выбор целевого сервиса или группы экземпляров монолита.
Локальная проверка JWT по JWK и работа с подписанным device ID.
Rate limiting для нагруженных маршрутов корзины и заказа.
Краткосрочная защита от повторной отправки запросов.
Retry-политики, circuit breaker и ограничение нагрузки при росте задержек.
Резервный upstream для поддерживаемых сценариев и передача trace-контекста.
Account Facade: перенос пользовательского контура
При интеграции с новым сервисом мастер-данных часть пользовательских данных уже принадлежала Customer-сервису, а часть логики и таблиц оставалась в монолите. Переносить авторизацию, профиль, адреса, checkout и CRM одним релизом было рискованно.
Account Facade объединил источники и сохранил привычные для витрины контракты, не становясь новым долговременным владельцем customer-домена.
Проверка JWT, профиль и адреса из Customer-сервиса.
Необходимый read-only пользовательский контекст из PostgreSQL.
Избранное, сохранённые банковские карты и часть расчётов корзины.
Генерация QR-кода профиля.
Проксирование операций, которые пока должны оставаться в монолите.
Управляемая миграция
Режимы proxy, service и shadow позволяют сравнить новый путь со старым, затем переключить чтение или запись и при необходимости вернуть трафик в монолит.
Профиль, избранное и ресурсоёмкая генерация QR разделены между группами экземпляров, чтобы тяжёлая операция одного типа меньше влияла на остальные запросы.
Мониторинг и наблюдаемость
В распределённой архитектуре важно видеть не только итоговую задержку, но и конкретный компонент, в котором она возникла: приложение, кэш, база данных, Elasticsearch или внешний API. Поэтому observability развивалась одновременно с сервисами.
Структурированные логи в ECS-формате и сквозной traceparent.
Elastic APM и отдельные spans для HTTP, PostgreSQL, MongoDB и Elasticsearch.
Prometheus-метрики и часть агрегированных показателей в ClickHouse.
Cache hit/miss для уровней хранения.
Startup-, readiness- и liveness-проверки.
Диагностические команды платёжного и фискального контуров.
Платежи и фискализация
С апреля 2025 года команда Lachestry участвует в развитии существующих payment- и receipt-сервисов Lime. Работа охватывает сценарии, где результат внешней операции может не вернуться синхронно и требует отдельного восстановления состояния.
Яндекс Сплит, SberPay, отмены, возвраты и восстановление статусов.
Периодические проверки проблемных операций и диагностические команды.
События через Kafka и RabbitMQ, операционные механизмы повторной отправки.
Авансовые, полные и возвратные чеки, callbacks CloudPayments и CloudKassir.
Платная доставка
Параллельно команда развивала бизнес-функциональность интернет-магазина. Механизм платной доставки затронул расчёт корзины и заказа, правила бесплатной доставки, передачу данных в платёжный и фискальный контуры, НДС и интеграционные контракты.
Он дал бизнесу возможность управлять стоимостью исполнения заказа. Публичные выводы о влиянии на выкупаемость и операционные расходы потребуют подтверждённых данных Lime.
Результаты
Главный результат первого этапа — снижение зависимости наиболее нагруженных пользовательских сценариев от одного Laravel-монолита и одной операционной базы данных.
Появился контролируемый слой API-кэширования.
Каталожное чтение и фильтрация частично переведены на Elasticsearch.
Внешние геопровайдеры изолированы в самостоятельном сервисе.
Пользовательские и критичные маршруты получили отдельный Gateway.
Начался поэтапный перенос пользовательского контура через Account Facade.
Сформирована общая платформа разработки и эксплуатации Swoole-сервисов.
Расширена сквозная наблюдаемость при одновременном развитии монолита, платежей, фискализации и доставки.
По наблюдениям проектной команды, последующие пиковые периоды проходили стабильнее: нагрузка распределялась между специализированными сервисами, а повторяющиеся чтения не всегда доходили до монолита.
Что показал проект
Работа не сводилась к замене фреймворка или механическому разделению монолита. Ключевой задачей стало определение границ ответственности.
Какие данные можно кэшировать и кто владеет бизнес-логикой.
Какие запросы можно безопасно вынести без смены публичного контракта.
Где нужен ограниченный fallback, а где он создаёт риск двойной записи.
Какие операции требуют отдельной идемпотентности и восстановления.
Как провести миграцию без одновременной переделки всей платформы.
В результате Lime получила постепенно развиваемую архитектуру, совместимую с существующей системой и процессами команды. Lime и Lachestry продолжают совместную работу над интернет-магазином, сочетая развитие бизнес-функциональности с последовательным устранением архитектурных ограничений.