Реклама. ООО «СМ ЛАБ». ИНН 7713488827. Erid 2RanynHc2ty
Реклама. ООО «СМ ЛАБ». ИНН 7713488827. Erid 2RanynHc2ty

Когда видишь компанию со стороны, одни вещи понимаешь, а другие остаются секретом. О том, что SM Lab отвечает за IT-решения в группе компаний «Спортмастер», можно догадаться уже по названию и логотипу. Но, например, сколько разработчиков заняты этими решениями? Какие именно у них проекты? Это куда менее очевидно.

Мы проводим конференции по разным IT-направлениям, на них неоднократно выступали спикеры из SM Lab, и некоторые вещи можно понять по их докладам. Например, на Mobius рассказывали про «Генерацию этикеток для термоп��интеров на основе языка разметки ZPL», а на Heisenbug помогали другим с «Первыми шагами в нагрузке».

А на этой неделе SM Lab примет участие в нашей Java-конференции JPoint, и я решил, что сейчас самое время задать вопросы о Java-разработке сотрудникам самой компании. Публикую результат, в котором соединены вместе ответы нескольких разных людей.


— Что вообще такое SM Lab? Что именно там делают, какие языки и технологии используют?

— SM Lab — ИТ-компания в составе группы компаний «Спортмастер». Мы трансформируем бизнес-процессы, переводя их в цифровое пространство, и создаём уникальные технологические решения для ритейла. Развиваем флагманские продукты — продающие сайты и мобильные приложения, разрабатываем внутренние продукты, поддерживающие бизнес-процессы компании — платформы, сервисы, back-office системы и другое.

Мы используем Java 21, Kotlin, Spring, Oracle 19.5, JS, Vue.JS, Swift, Elasticsearch, 1С, K8s, MongoDB, Nginx.

— А если говорить конкретно про Java-разработку: например, сколько разработчиков, какой технологический стек?  

— SM Lab насчитывает более 120 Java и Kotlin разработчиков (это суммарно). Среди них есть и чистые джависты, и чистые котлинисты. По процентному соотношению Java/Kotlin сейчас примерно 70/30. 

Наш стек конкретно в JVM-мире: Java, Kotlin, Spring, Prometheus, Docker, ElasticSearch, RabbitMQ, Kafka, Oracle, K8s, Grafana, Maven.

— Можете привести пример того, как Java-разработчики сталкиваются с предметной областью? Какая задача у них может возникнуть в SM Lab, которая вряд ли возникла бы в компании совсем другого профиля?

— Например, на Java у нас написан продукт «Касса». Касса — это ключевое понятие в ритейле. Этот продукт помогает эффективно решать критически важные для retail-компании задачи по исполнению сделки с клиентом: прием платежей, выдача товаров и оказание услуг, формирование фискальных чеков. А также предоставляет данные, чтобы учитывать эти операции для формирования отчетности. 

Тут мы находимся на передовой при изменениях в законодательстве или просто взаимодействии с покупателями. Поэтому при работе с чеками пришлось подробно разбираться в реквизитах и тегах для ФНС (особенно при печати чеков коррекции), некоторые моменты приходилось уточнять непосредственно в законодательстве на сайте КонсультантПлюс. Часто ли в мире Java-разработки  открывают этот сайт? :) 

— А если не привязываться к специфике: можете ли подробно рассказать о любом крупном и «долгоиграющем» проекте с Java-разработчиками? Давайте пойдём с самого начала: когда и как он возник и развивался?

— Первый интернет-магазин «Спортмастера» появился в начале 2010-х. Он был реализован на платформе 1C-Bitrix. В результате роста количества покупателей она перестала справляться с нагрузкой, из-за чего были попытки её оптимизировать и доработать. Через какое-то время пришли к выводу, что дальнейшие усилия в данном направлении бессмысленны, и было принято решение о создании собственного сайта. 

Примерно в 2013 году началась работа по проектированию и реализации. Проект разрабатывался на Java 1.8 с использованием Spring 4, для полнотекстового поиска использовался ElasticSearch 1.4, распределенный кеш был реализован на Hazelcast. Для работы сайта нео��ходимо было загружать много разнообразной информации из бэкофисных систем. Для этих целей был выбран ETL Pentaho.

В 2015-ом году новый сайт вышел в продакшн. Не все запланированное было реализовано: админка тогда осталась в Битриксе. С этого момента сайт начал быстро развиваться и обрастать новой функциональностью. Стали появляться новые сервисы и интеграции. Появилась мобильная версия сайта, реализованная на Angular и использующая API проекта, появился «Киоск» — специальная версия для больших тач-устройств, установленных в магазинах. Через какое-то время появилось первое мобильное приложение, которое также использовало наш API. Также была реализована версия сайта для контакт-центра.

Активное развитие продолжалось примерно до середины 2018 года. В это время все больше набирал популярность онлайн-формат, что кратно увеличило аппетит бизнеса: захотелось быстро поднимать аналогичные сайты для других бизнес-направлений. После оценки возможности переиспользования наработок мы поняли, что получившийся монолит будет трудно адаптировать под другие бизнес-требования. Также к этому моменту накопилось определенное количество труднорешаемых проблем: поддержка админки в битриксе съедала все больше ресурсов, неудачное решение с ElasticSearch не позволяло обновиться на актуальную версию, а используемая очень сильно устарела, проект не успевал адаптироваться к постоянно возрастающей нагрузке.

В связи со всем этим было принято решение об очередном перепроектировании.

Выделили определенный набор требований:

  • общую функциональность (корзина, товары, контент и т.д.) вынести в отдельные сервисы

  • кодогенерация по контрактам

  • отзывчивость и масштабируемость

  • сокращение времени на поддержку

Таким образом, в 2020 году началось создание новой версии сайта СМ 3.0 — уже на собственной платформе, которую решили писать на Kotlin + Spring 5 с использованием реактивного стека. Сразу же была заложена возможность кодогенерации по контрактам. Для этого используется доработанный OpenAPI Generator. Для снижения затрат на поддержку с самых первых дней много внимания уделялось написанию автотестов. На текущий момент у нас используются практически все виды автотестирования. На бэкенде мы используем kotest с собственными расширениями для модульного и интеграционного тестирования. Для автотестов вокруг Selenide нарастили свой фреймворк с кодогенерацией, распараллеливанием, шахматами и поэтессами. Плюс активно используем wiremock для API-тестов.

Много споров было вокруг того, какую архитектуру выбрать, но в итоге предпочтение отдали набиравшей популярность DDD. На данный момент можно констатировать, что у нас получилось реализовать чистый DDD.

Фронт реализовали на VueJS 2, но в прошлом году мы успешно мигрировали на третью версию.

Для сокращения ручного труда с самого начала разработки мы стремились к чистому CD, об этом уже рассказывал мой коллега на Joker. И в итоге у нас это получилось: на данный момент момент пайплайн в GitLab сразу же после мержа ветки разворачивает новую версию приложения в Kubernetes. Для этого была проделана следующая работа: мы перешли на trunc-based разработку, был создан свой Feature Toggle-сервис, научились поднимать короткоживущие динамические окружения для проведения автотестов. Также для удобства ручного тестирования и демонстрации функциональности добавили возможность поднимать собственные окружения для любой ветки. Для повышения качества кода в пайплайн мы также интегрировали статический анализатор Detekt, настроили QualityGate в SonarQube, который следит за минимальным покрытием кода тестами, интегрировали DependencyCheck от OWASP, который позволяет автоматизировать поиск уязвимостей во внешних зависимостях.

Разбиение монолита на сервисы помогло отбросить всю дополнительную работу и сосредоточиться именно на сайте.


Раз был упомянуто выступление на Joker, я решил заодно посмотреть его и кратко пересказать для Хабра суть. 

Она оказалась такой:

Ранее в SM Lab после деплоя возникало небольшое снижение трафика. Дело было в том, что обычно всё работает в «прогретом» состоянии, а после деплоя нового кода сервису сначала требовалось время на прогрев. И в такие моменты пользователь мог получать ответ с большой задержкой, расстраиваться и уходить на другой сайт. В такой ситуации деплоить хочется пореже и по ночам, но это увеличивает time-to-market и в целом осложняет жизнь.

Рассмотрев разные варианты, в компании пришли к следующему: при балансировке нагрузки с Kubernetes использовать решение для так называемой EWMA-балансировки (exponentially weighted moving average). В этом случае запросы пользователей по умолча��ию отправляются туда, где они с большой вероятностью окажутся обработан быстро. Так что «прогреваемые» инстансы не получают сразу же много запросов и не подводят всех этих пользователей долгой обработкой, а постепенно «входят в строй». При этом важно не раскатывать апдейт одновременно везде, а немного распределить его во времени (чтобы не оказалось, что всё прогревается одновременно, и отправлять запросы пользователей для быстрой обработки пользователей «некуда»). 

Применив это, получилось в разы снизить время ожидания для 99-го перцентиля, а благодаря этому — деплоить быстрее и спокойнее, сократить time-to-market и уйти от «ночных деплоев».


А ещё одно выступление SM Lab на JPoint было про архитектурные вопросы:

В вечном выборе «аджайл или водопад» нет единственного верного ответа, на практике компании обычно выбирают что-то «между», потому что обе крайности с недостатками. Если пытаться «по-водопадному» спроектировать всё заранее, неизбежно потом сталкиваешься с тем, что на практике многое оказывается не как было «на бумаге». Но если совсем уж «импровизировать на ходу», тоже можно обнаружить, что забрёл не туда: какие-то важные требования остались невыполненными, и реализовать их уже сложно, так что всё-таки надо было сразу зафиксировать главное.

А что будет этим «главным»? В выступлении разбирают, как в SM Lab могут выглядеть ASR (Architecture Significant Requirement) на конкретном небольшом примере «полезного чат-бота».


После ответов компании картина частично стала мне яснее, однако всё-таки не полностью. Но на нашей конференции JPoint, которая пройдёт уже 3-4 апреля, SM Lab будут присутствовать — так что если у кого-то из её участников тоже остались вопросы, то вот там будет удобная возможность всё доспросить в перерывах между докладами.