Pull to refresh
109.34
Петрович-Тех
DIY, e-com, экосистема сервисов

Про фугу, Антонио и парашют, или Как мы разрабатывали каталог строительных материалов

Reading time9 min
Views3.4K

Мы делаем суровый DIY для требовательных прорабов. Суровый, потому что он про шестиметровую доску естественной влажности, кольца ЖБИ, трехметровый гипрок и сыпучку палетами. А требовательные, потому что малейшие изменения в UI и UX приводят к «Чего началось-то, нормально же общались».

Интернет-магазин строительных материалов — это когда в каталоге названия товаров от 20 до 140 символов — и в них все важное. Когда 4,8 миллионов записей о связях сопутствующих товаров, когда цена указана за метр, продается в упаковках и купить можно не только integer. Когда порой клиенты не знают, что им нужно и как это называется: нейминг в таких товарах — это богатая тема, достойная отдельной статьи, это вам не трусики: стринги, танго, добрая классика «75+».

Когда товары колеруются, пилятся и поднимаются в грузовом лифте, а если его нет — то пешком. И мы точно должны знать, сколько стоит поднять 1 лист гипсокартона пешком на 25-й этаж в уездном городе N по конкретному адресу.

Когда доставка всего за 2 часа и пересчет доступности товара для продажи и логистического плеча от ХАБа до сборки заказа, а также способа оплаты, должен учитывать сотни параметров. Мы знаем, где сейчас находится каждый товар: город, подразделение, склад, место и ячейка хранения. Мы знаем его каналы поставок и графики перемещений с точностью до минуты. В момент оформления заказа знаем, откуда повезем. Чтобы успеть вовремя, еще в тот момент, когда оплата проходит долгий путь от «одного касания пользователя» до облачной кассы и ОФД, у нас уже запускается машина времени, которая распределяет заказы по рейсам, водителям, машинам, строит маршруты. А на рабочем месте комплектовщика появляется заказ на сборку. И если что-то в этой цепочке изменилось, хотя бы один параметр, то он должен учитываться, пересчитываться и отображаться для пользователя — все должно быть таким реактивненьким, как сейчас модно.

Как все начиналось

Мы осознали, что у нас на проекте 23 разных крестика у модалок, каждый экран — это новая кнопка и новый CSS. Вносится изменение в корзину — ломается каталог. Добавили новый тултип в листинге — сломались шаблоны страниц товара. На складе в Балашихе изменили место хранения у категории — сайт должен это увидеть, чтобы показать информацию о наличии и доступности товара. Только на сайт вместе с ячейкой, пришло название, описание, сопутствующие и аналоги, галерея фото и видосы с бородатым мужиком, монтирующим парашюты, а вслед за видосами пришел админ с вопросом: «WTF, сколько вы будете сервера насиловать, когда перепишете?»

Тогда и решили, что пора все переделать. Монолитность, ненадежность, избыточность, админы опять же, игнорировать это все — плохая примета.

Как декомпозируешь, так и до продакшена понесешь

Начали с плана, разбив блоки на front и back, оценив срок по принципу трех «П». При этом разработку планировали вести параллельно. Вот что мы сделали:

  1. Собрали требования по функционалу от разных подразделений (сходили в гости к маркетингу, SEO, закупкам, контентщикам, контакт-центру, коммерсам и т. д.).

  2. Провели исследование и выбрали технологии.

  3. Спроектировали системы обмена данными.

  4. Спроектировали БД для хранения накопленной информации.

  5. Написали протокол взаимодействия с клиентом (API).

  6. Создали и согласовали контракты по работе с API, выполнили генерацию моков.

  7. Создали дизайн-систему.

  8. Выполнили прототипирование интерфейсов.

  9. Создали дизайн интерфейсов.

  10. Выстроили архитектуру бэкенда и фронтенда.

  11. Выполнили реализацию, в которую вошли:

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

    2. Реализация агрегации промежуточных данных. Например, вычисление цен из временного регистра, агрегация остатков по складам, определение активности товаров и т. д.

    3. Сбор всех необходимых данных с учетом нового дизайна.

    4. Реализация серверной части приложения.

    5. Реализация сервисов бэкенд.

    6. Верстка шаблонов.

    7. Реализация клиентской части приложения.

  12. Подготовили тестовое окружение.

  13. Подготовили продакшн окружения.

  14. Выполнили интеграцию (переключение с моков на API).

  15. Провели тестирование на стейдже.

  16. Исправили дефекты и подготовили запуск на продакшн.

  17. Запустили.

Чтобы таска была хороша, она должна вылежаться

Требований по каталогу у нас на годы вперед, поэтому мы отобрали лишь те, что можно было отнести к базовому функционалу. Задача стояла такая: переписать, заложить основы, не пытаться сразу всех удовлетворить. Но все договоренности, планы и согласования оказались бредом для сельской паствы. Все равно документация оказалась сырой, дизайн и решения меняли на ходу. После демо появлялись новые требования, не редкими были и доработки в макетах, обменах данными, структурах данных и API.

Разработка «вид сзади»

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

Весь код для обмена и работы с данными находился в одном репозитории. Проект развивался, обрастал как новым функционалом, так и избыточностью. И каждая новая фича в каталоге плюсовала время на получение и агрегацию данных. Накопленное легаси сделало управление и доработки обмена данными трудоемкой задачей. Со временем от real-time-чтения мы перешли на агрегацию и хранение информации в специальных таблицах для того, чтобы ускорить чтение, а также приделали горячее кэширование. Проведя анализ накопившегося, мы решили существенно изменить имеющееся решение, чтобы обеспечить высокую скорость обмена информацией, снизить время на доработку и добавление новых обменов, повысить скорость ответа API. В общем, перейти к сервисной архитектуре от монолитной.

Начали с обменов. Необходимо было выбрать брокер очередей. Проведя исследование среди популярных брокеров ActiveMQ, RabbitMQ, Apache Kafka и прочих, остановились на ActiveMQ (так как он был уже в стеке) и Kafka (как потенциально перспективный для компании). Рассматривая инструменты, мы сделали упор на масштабировании и гарантии приема сообщений, по итогам экспериментов, выбрали Kafka. Естественно, при этом пришлось немного поработать с клиентом, так как по идеологии Kafka именно клиент должен быть «умным» и уметь правильно обрабатывать сообщения.

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

Как мы уже говорили, к началу работы с каталогом текущая версия была реализована в едином приложении, что являлось определенной сложностью, поскольку не было возможности обновить часть приложения. За годы разработки проект накопил достаточное количество легаси, поэтому изменения в одной части приложения приводили к неожиданным ошибкам в другой. Это означало, что и тестирование, в том числе регресс, необходимо было проводить, даже если запятую убрали. В итоге мы выделили все API в независимые сервисы. Для описания документации и введения стандарта взяли за основу спецификацию OpenAPI 3 и правила версионирования SemVer. Описали свой перечень правил и прежде всего разработали контракт данных. Договорились «на берегу».

Для обработки сообщений из очереди kafka использовали демон на php. Для хранения промежуточных данных из обмена создали отдельный instance БД. Полученные данные — сырые, и требуется постобработка, такое решение позволяет разделить нагрузку. В работе новый формат обменов показал себя успешно, поэтому мы продолжили развивать его и масштабировать на весь каталог.

При выборе хранилища БД мы решали поставленную задачу: чтобы API отвечали в пределах 50 – 100 мс. Так же мы планировали использовать в разработке SSR на Node, что тоже наложило требования к скорости ответа API и отказоустойчивости.

Для того чтобы организовать хранение данных каталога, в качестве основной БД мы выбрали Redis, так как за время работы был накоплен достаточный опыт использования и он неплохо организовывается в кластер. Настроили Redis Persistence c записью в один мастер и две географически разнесенные readonly-реплики. В мастер пишут обмены, а реплики используются для чтения в API-сервисах. Для репликации использовали опцию AOF, поскольку это более надежный вариант. Кроме того, провели изучение формата хранения данных и способа сериализации/десериализации данных PHP. По итогам исследования расширение igbinary показало лучшие результаты, чем json, php-сериализатор или msgpack. Для фильтрации и сортировки данных в каталоге выбрали elasticsearch, так как в нашем стеке этот инструмент уже был и его производительность нас устраивала.

При внедрении в продакшн сервисы API развернули на существующей инфраструктуре, а вот для SSR подготовили отдельные серверы с прослойкой кеширования на Varnish.

Per aspera ad astra

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

Для поиска проблемы использовали профайлер, дебаг, нагрузочные тесты, читали системные логи, но при этом получали необъяснимые зависания в разных местах кода. В итоге, проводя эксперименты с нагрузочными тестами, заметили совпадение пиков нагрузки с запусками агрегации данных и записи их в redis. Причина была в том, что для оптимизации работы для записи в redis, мы использовали загрузку батчами, но батчи были достаточно большими и запрос на запись в мастер одного батча мог занимать много времени. Но с учетом репликации AOF, которая хранит журнал запросов, все эти запросы выполняются на slave. А так как redis однопоточный, то запросы на получение данных из API сервиса в это время простаивали в очереди. После уменьшения количества объектов в батчах на запись, подобные пики практически перестали воспроизводиться. А поскольку Redis требователен к процессору, CPU были закреплены за виртуальными серверами, обслуживающими кластер Redis.

Фронтмен должен быть красив! Это для начала

За годы работы наследие накопилось и во фронтовой части приложения: скелеты в шкафу, костыли, скелеты на костылях, палки... Поэтому front принял волевое решение, что все-таки нужен свой велосипед и стали пилить свою дизайн-систему.

Мы 11-е в рейтинге среди е-коммов, амбиций дофига, хотим, как у всех, чтобы по-взрослому. Без своей дизайн-системы не продать нам ни галоши, ни обои, ни полы с подогревом. И опять же, 23 крестика у модалок, как тут без стандартизации дизайна, удобства правок, уменьшения time-to-market — вот эти все умные слова. Дизайн-систему начали с малого. Родился UI-kit без документации, молодой и полезный, как микрозелень, это, конечно, усложнило работу над каталогом. Но мы верим, что заложили фундамент, что дьявол в деталях, и наш Kit рассказывает и показывает, как делать хорошо цифровые продукты в DIY для всех: и для суровых строителей, и для девушек с собачками.

На фронте у нас есть устоявшийся стек технологий: React, RxJS, Webpack, SCSS, Typescript. Но помимо дизайн-системы, мы поставили перед собой еще одну задачу: сделать SSR (Server Side Rendering) клиентского кода на Node JS. До этого использовали smarty. Таким образом мы смогли применить один код как на клиенте, так и на сервере.

Еще про амбиции: CustDev явным образом сказал: «Нужна автоподгрузка товаров на странице, потому что тыкать в кнопки «Показать еще», когда ты в варежках и на объекте, — не вариант!» Нужно было решать задачу, при этом сделать удобно и не отрисовывать 1000 товаров.

В общем, кто хоть раз делал каталог, скажет: «В следующей жизни буду разработчиком админок». Потому что он делал SEO, интеграцию с маркетинговыми инструментами. А когда у тебя SPA, а логировать и отправлять события все равно надо, вот тут, кроме как «Всевышний терпел и нам велел», лучше и не скажешь.

Краткая история «ССР»

При работе над SSR тоже не обошлось без геморроя, у нас возникли проблемы с утечкой памяти. Такого рода проблемы обычно не решаются быстро, и поиск утечек занимает достаточно много времени. Но мы справились и для надежности реализовали кластеризацию Node-приложения, которая позволила нам в случае появления новых утечек или иных проблем с падением приложения, переключать пользователей на другую ноду кластера и перезапускать упавшую.

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

Мы в ответе за фичу, которую прикрутили

Не так страшны первые 90% проекта, как вторые 90% проекта.

У нас есть отработанная схема запуска такого рода больших фич в продакшн, и каждая крупная фича проходит несколько этапов тестирования и исправления дефектов. Тестирование можно разделить на три блока: тестирование API, верстки, функциональное тестирование GUI. 

При тестировании API проверяем бизнес-логику приложения. В итоге было описано и автоматизировано свыше 1600 тест-кейсов согласно тестовой модели. Если говорить про верстку, то нужно понимать, что тестировать нужно полную и мобильную версию, а также разные браузеры и разрешения.

И последний этап — функциональное тестирование графического интерфейса. Но перед этим нужно описать и проревьюить все тестовые сценарии (документация и опыт нам в помощь!). В итоге получилось более 500 тест-кейсов для десктопа и свыше 400 для мобайла.

Когда мы поняли, что все критические дефекты исправлены, все важные для SEO моменты учтены и четко работают, когда мы получили фидбек от отдела маркетинга, что все данные отправляются в разного рода маркетинговые инструменты, мы все равно запустили новый каталог на несколько групп добровольцев из аутсорсингового контакт-центра, которые работают на сайте. И только получив их благословение, начали переключать новый каталог на пользователей. А лучшим доказательством того, что мы молодцы, стала тишина от наших пользователей. Мы все разобрали до основания и собрали иначе, а требовательные прорабы не заметили.

И кстати, фуга — это не про фугу Баха, а про шпаклевку «Фуген». А Антонио — это третий по частотности поисковый запрос. Конечно, ищут не Антонио и не Рикардо. Это автокоррекция «Ветонит» на IOs. А парашют — это не про прыжки, а про теплоизоляцию, но об этом — уже в следующей истории…

Фото парашютов прилагается.

Дюбель для теплоизоляции Bau-Fix 10х100 мм
Дюбель для теплоизоляции Bau-Fix 10х100 мм
Tags:
Hubs:
Total votes 3: ↑3 and ↓0+3
Comments13

Articles

Information

Website
petrovich.tech
Registered
Founded
Employees
201–500 employees
Location
Россия