Наш склад размером с две Красные площади и высотой в 5 этажей работает круглый год и никогда не спит — 24/7 364 дня в году (единственный выходной — 1 января). У нас хранится и обслуживается более 8 000 000 товаров, каждый день на смену выходит более 300 операторов. Они работают с товаром, поступающим со всего мира, и собирают заказы для пользователей из четырех стран: России, Украины, Белоруссии и Казахстана. На таких масштабах бизнес требует безупречной автоматизации.
Под катом я, Паша Финкельштейн — тимлид команды разработки и автоматизации склада — расскажу, во что может вырасти open source решение, если к нему приложить хорошую команду разработки и вполне конкретную бизнес-задачу.
Базовая логика работы
Три главных процесса любого склада: приемка товара, его хранение и отгрузка. Упрощенно цикл нашего склада выглядят так: первичная идентификация, контроль качества, размещение, подбор и резервация для заказа, поиск, сортировка, упаковка, передача в службу доставки. При возврате товара клиентом цикл повторяется. Каждая физическая сущность, участвующая в этих процессах, имеет свое информационное представление, например: грузовик, товар, ячейка шкафа, посылка, упаковочный материал, контейнер и т.п. Все значимые движения и изменения статуса товара транслируются в учетные системы и абсолютно каждое действие с товаром внутри склада логируется.
WMS (Warehouse Management System) контролирует жизненный цикл каждого товара, находящегося на складе, с момента прибытия грузовика с товарами поставщика на склад и до отгрузки товара клиенту.
Специфика автоматизации fashion
Наша компания работает в сфере fashion и lifestyle, что ставит определенные задачи в работе склада: товар может быть хрупким (очки, часы), нестандартного размера (зимние сапоги или бижутерия), премиальным (в особой упаковке) — или обладать другими специфическими характеристиками, которые склад должен учитывать. Поэтому от использования ручного труда в зонах хранения полностью отказаться невозможно.
Все остальные процессы автоматизированы — приемка товаров, перемещение к зоне отгрузки, сортировка, упаковка и подготовка к отправке. Каждый из этих процессов требует специального оборудования и операционного процесса. Магия случается, когда все эти процессы «склеиваются» и начинают работать вместе — благодаря нашим системам.
Любая оплошность в автоматизации склада — будь то интерфейс, способствующий ошибкам оператора, неоптимальный процесс и т.п. — это задержки отгрузки, простой всего комплекса, огромные потери. Кроме того, каждой ошибкой мы формируем негативный клиентский опыт. Поэтому нам важно, чтобы склад работал как часы.
Open source и путь к собственной разработке
На этапе открытия мы использовали внешний склад. С ростом объемов мы стали понимать, что нам нужен полный контроль над операционными процессами и высокая скорость изменений этих процессов, поэтому мы решили двигаться в сторону собственного склада и разработки.
Главный вопрос, который тогда встал перед нами, — проработка во всех деталях операционных процессов. Вплоть до того, куда и как ходят сотрудники, сколько сканирований они делают и т.п. И уже над этими процессами необходимо было развертывать WMS, управляющую операционной деятельностью и автоматизирующую рутинные операции.
Для начала взяли open source решение на Java и после решили собрать собственную команду разработки, тем более, что уже есть подходящая основа. Мы наращивали функциональность, затем взялись и за ядро системы: избавлялись от legacy и толстого клиента, проводили рефакторинг, разрабатывали новые сервисы для поддержки операционных процессов.
Этапы автоматизации
Основные изменения выполнялись «волнами», вместе с перестройкой самих процессов.
На сегодняшний день он пережил девять этапов модернизации, и останавливаться на этом мы не планируем.
- На первом и втором этапах мы автоматизировали процессы отгрузки заказов — добавились конвейеры, логика по сортировке товаров, автоматизированная сортировка заказов по паллетам.
- На третьем и четвертом этапах сосредоточились на процессах приемки: научились разделять потоки входящих товаров по разным типам и зонам хранения.
- Пятая фаза добавила автоматизированные лифты между этажами — так началась работа в зоне хранения.
- Шестая фаза была самой ответственной, когда мы замкнули зоны приемки и отгрузки, закольцевав таким образом всю автоматизацию.
- На седьмой и восьмой фазе мы внесли изменения в процессы в зоне приемки и добавили новые зоны, лифты и конвейеры: масштабировали уже имеющуюся автоматизацию.
- Девятой фазой присоединили к складу новое здание и интегрировали его с существующей системой автоматизации.
Реализация
Наши основные технологии: Java, Postgres, Wildfly, Redis, ActiveMQ.
WMS написана на Java 8. Но не так давно мы поправили последний модуль, который мешал переходу на Java 11, обновимся в ближайшей перспективе.
Под WMS отведена серверная стойка, установленная прямо на складе. Это даёт нам гораздо больше уверенности в том, что WMS будет работать даже в том случае, если электричество и/или интернет отключат. Единственное, что пострадает — сообщения в товароучетную систему придут с задержкой. В качестве сервера приложений используется WildFly, правда, пока не последней версии. Миграция на последнюю также в планах. Для переезда всё уже написано, но не успели пока провести функциональное и нагрузочное тестирование, да и перед новым годом загрузка относительно высокая. Также используется проверенный ActiveMQ.
Данные мы храним в PostgreSQL. Основной сущностью в нашей системе, очевидно, является товар. Иногда сотрудники склада придумывают обходные способы упростить себе работу, например, сканируют один и тот же штрих-код 50 раз, а сам товар просто перекидывают вручную без сканирования, не вдаваясь в детали, джинсы это или футболки, поэтому мы ввели этикетки, идентифицирующие конкретную единицу товара, поддержав это в инфраструктуре. Информация об этих единицах как раз и хранится в 2-терабайтной базе PostgreSQL.
Большую часть места там занимают даже не товары, а аудит действий работников склада. Будучи критичной для бизнеса системой, склад должен знать, почему что-то появилось в системе или пропало — мы не можем допустить не трассируемых изменений. Как раз сейчас мы думаем над тем, чтобы вынести эту часть базы в отдельную сущность в MongoDB.
Рабочие станции сотрудников склада — это тонкие веб-клиенты. Где-то на старте автоматизации все это работало по принципу толстого клиента, что создавало определенные сложности, в частности, при крупных релизах, включающих в себя изменения в интерфейсе: порядка 150 рабочих станций приходилось обновлять вручную. Это и тот факт, что мы не могли релизиться без простоя, ставило нам ограничения — мы могли деплоиться не более двух раз в неделю, ранним утром, когда заканчивает работать ночная смена, что никак нельзя назвать удобным графиком. Сейчас мы перевели WMS в веб и к концу года окончательно откажемся от толстых клиентов, что очень упростит нам изменения пользовательского интерфейса. Веб и добавленная на одном из этапов кластеризация снимают ограничения на частоту и время релизов — уже сейчас пользователи узнают о релизах, только если что-то пошло не так.
Есть на нашем складе и интересная «экзотика». Например, упомянутый в Технорадаре Haskell, на котором написан бэкенд визуализации item-сортера (это такая машина, которая может составлять товары из одной посылки вместе и отдавать их оператору на сборку). Там чисто вычислительная задача, которую удобно решать в функциональном стиле. Естественно, никто не собирается использовать Haskell для каких-то крупномасштабных проектов.
Еще один элемент склада, который мы упоминали в статье о Технорадаре — самописная стейт-машина, которая «следит» за правильной последовательностью действий с каждым товаром. Она, как и вся система, развивалась итеративно, начавшись с простого набора ограничений. Сейчас это очень удобная штука, глубоко интегрированная в нашу систему. Мы надеемся в ближайшем будущем выложить ее в open source — возможно, она будет полезна не только нам.
Оборудование для автоматизации
Какая же автоматизация без оборудования! Весь склад опутан целой сетью конвейеров.
Упомянутый выше item-сортер работает на этапе отгрузки, позволяя раскладывать десятки тысяч единиц собранного со стока товара по конкретным заказам. В свое время сортер избавил наших операторов от необходимости путешествовать с тележкой по всему складу, чтобы собрать нужные товары. Заказы дробятся, каждый оператор собирает товары только со своего этажа (экономя время на перемещениях), а сортер заботится о том, чтобы товары с разных этажей попали в нужные заказы автоматически. Изменение операционного процесса в 4 раза ускорило сборку заказа и существенно сократило количество ошибок.
Все автоматизированное оборудование нам предоставляет партнер. За управление конкретными агрегатами у них отвечает собственная система, которая размещена в серверной стойке по соседству с нашей WMS. Между системами настроена интеграция на довольно высокоуровневом протоколе — общаемся по SOAP. Из своих операционных процессов внутри WMS мы обращаемся к их системе, когда нам, например, нужно переместить контейнер с товаром из точки A в точку B. Т.е. с точки зрения нашей системы вся эта автоматика выглядит довольно просто, несмотря на ее реальную внутреннюю сложность.
Конечно, эта видимая простота заработала далеко не сразу. На первых стадиях автоматизации у нас была «взаимная притирка» технологий. Однажды конвейер в буквальном смысле сжег наш товар — скорость конвейерной ленты была слишком высокая, она «зажевала» товар и он сгорел, что заблокировало сборку других заказов. Пожалуй, самая тяжелая история произошла на старте автоматизации, когда мы запускали первую фазу. Еще вчера склад был полностью ручным, а сегодня, после переключения рубильника, он должен стать автоматическим. Но ничего не заработало: из-за ошибки в интеграции системы неправильно интерпретировали сообщения друг друга, что вылилось для нас в несколько дней простоя склада и многомиллионные потери.
Сейчас партнер присутствует на нашем складе, планирует расстановку оборудования вместе с нами, когда речь идет о новом витке автоматизации, помогает тестировать новые блоки.
Команда и scrumban
Развитием всей этой системы сейчас занимается команда из 12 человек. На одном из последних этапов в пиках модернизации, когда отдельно автоматизированные процессы должны были объединиться в нечто целое, участвовало до 20 одних только разработчиков (тот этап потребовал 132 человеко-месяца и включал более 1500 коммитов). Но по мере окончания масштабных преобразований некоторые люди решили изучить Go или Python и перешли в другие команды разработки.
В команде у нас есть «классические» проджект менеджеры, совмещающие в себе функции продакта и проджекта со стороны ИТ (в среднем, один ПМ на 5-6 человек). В его задачи входит общение с нашим основным заказчиком — складом в лице его директора и отдела развития операционных процессов. Со своей стороны мы в большей степени заботимся о технической модернизации — выборе подходящего стека, обновлениях и т.п. — а ребята со стороны склада думают об оптимизации процессов.
Порой мы и сами уделяем время «R&D в поле». В буквальном смысле приезжаем на склад, общаемся со старшими смены, с рядовыми операторами, уточняем, какие у них есть проблемы, с чем удобно и неудобно работать. Иными словами, проводим исследования пользовательского опыта.
Благодаря такому подходу у нас, например, преобразился интерфейс рабочего места сотрудника, осуществляющего приемку товара. Изначально это был энтерпрайзный сложный интерфейс с множеством полей, кнопок и аббревиатурами вместо текстовых пояснений. Но мы постарались оптимизировать процесс, как и дизайн, сделав его более похожим на главную страницу поиска Google — не таким красивым, но очень функциональным. Чем проще интерфейс и чем меньше у оператора вариантов, куда ему нажимать и что сканировать, тем меньше ошибок (и затрат времени на их исправление).
А накопленные знания по оптимизации деталей теперь настигают нас в самые неожиданные моменты: как-то раз наша команда сидела в заведении и в один момент почти все участники засмотрелись на последовательность действий кассира. Секунд через 40 коллега озвучил общую мысль: «Не очень оптимально, можно упростить».
Хотя взаимоотношения между ролями в команде у нас вполне классическое, методологию разработки мы выбрали свою, назвав ее скрамбан (scrumban).
Мы много экспериментировали с методологиями, при том что «вводные» данные были нестандартны. Например, у нас были довольно редкие релизы. Упомянутое выше ограничение в два релиза в неделю действовало со стороны процессов, но по факту мы деплоились гораздо реже — в среднем раз в две недели. Кроме того, у нас была аппаратная часть автоматизации склада, разработка которой ведется внешней компанией по чистому waterfall, где все изменения расписаны на два года вперед со всей необходимой документацией. Однако сами последовать их примеру мы не могли: нам требовалось на регулярной основе вносить в систему какие-то изменения, а заставлять заказчика писать на каждое из них подробнейшее задание было бессмысленно.
Так что scrumban — это компромисс, который устроил всех. Мы используем итеративный процесс, но спринт для нас и есть релиз. Раз в месяц встречаемся с заказчиком и занимаемся релизным планированием: обсуждаем, что и на какой неделе мы выкатываем. Внутри спринта реализован канбан — с бэклогом задач, прогрессом и т.п. Правда, и этот процесс постепенно меняется — например, канбан доски у нас нет. Просто когда один разработчик заканчивает свою задачу, ему выдают следующую из пула в соответствии с планами на ближайший релиз и компетенциями самого разработчика.
Нам такой подход нравится. Он обеспечивает необходимую гибкость внутри итераций, а бизнес-заказчику дает прогнозируемость дат, к которым будут реализованы те или иные коммиты. И нам не так важно, как эта методология называется. Главное, чтобы все работало.
Не как у всех — на примере инвентаризации и мониторинга
Развивая операционные процессы, мы отталкивались от потребностей своей индустрии, поэтому у нас присутствует довольно много индивидуальных особенностей.
Хороший пример — инвентаризация. По закону ее необходимо выполнять на складе раз в год, но наши бизнес-требования определяют более пристальное наблюдение за стоком. Во-первых, мы хотим отражать на сайте актуальную информацию о наличии товаров, и во-вторых, той же актуальной информации требуют наши B2B партнеры, fashion-бренды. Поэтому инвентаризация у нас происходит ежедневно, 364 дня в году, полка за полкой во всем 5-этажном комплексе из нескольких зданий. И этот процесс целиком поддерживается нашей WMS — на готовом решении реализовать такое было бы тяжело.
Сейчас инвентаризация находится в процессе очередного обновления для повышения эффективности этого процесса.
Еще один пример собственной разработки — мониторинг. Он реализован через веб-клиент и позволяет отображать и отслеживать очень интересные метрики. Более того, для нас важно визуальное представление этих метрик. По сути мониторинг — это отрисованный в простенькой графике склад, где мы наглядно видим, в каких местах все работает хорошо, а где наблюдаются проблемы (вплоть до конкретного оператора). Главное, с таким представлением мы можем понять, почему возникают эти проблемы.
KPI складских работников и Redis
Внедрение новых технологий, обновления, рефакторинг — это все здорово. Но наш WMS работает в реальном бизнесе, поэтому здесь приходится решать не только эти задачи. Часть нашей работы — защита от внутренних «хакеров» — находчивых сотрудников склада, которые изобретают новые способы выполнить KPI в обход поставленной задачи.
Например, не так давно мы вынуждены были добавить в стек Redis, чтобы исключить возможность пользователям логиниться в систему с нескольких рабочих мест одновременно и реализовать таймаут сессии. Дело в том, что складские работники догадались, что работать под одним логином и получать премию за перевыполнение KPI гораздо выгоднее, чем повышать собственную производительность.
Поскольку для решения задачи бизнеса требовались изменения в самых разных местах системы, с технической точки зрения это было очень интересным челенджем.
На этом сюрпризы от складского персонала не закончились. Почти сразу после релиза сессии у нас начал падать PostgreSQL. Причины неожиданной деградации базы мы искали несколько дней, пока не обнаружили, что дело, опять же, в находчивости. Одна девушка часто ходила курить. Когда она покидала рабочее место, ее выбивало из сессии, а чтобы залогиниться обратно, необходимо найти старшего смены и просканировать его бейдж. Сокращая себе блуждания по складу, она просто оторвала штрих-код с одной из тележек и зафиксировала скотчем кнопку сканера, устанавливая на постоянное сканирование этого штрих-кода. И это могло бы долго оставаться незамеченным, если бы штрих-код не был с тележки, в которой лежало 800 единиц товара. При каждом сканировании генерировался огромный SQL-запрос для валидации товаров, который «убивал» базу таким «внутренним DDoS». Пришлось позаботиться и об ограничениях на количество сканирований в единицу времени и на количество товаров в тележке.
Таких историй накопилось уже довольно много, и мы постоянно сталкиваемся с новыми. При этом система должна каждый раз адаптироваться к новым условиям. В таких ситуациях нельзя ограничиться только административными методами — то, что произошло один раз, вполне может повториться.
Куда мы движемся дальше?
Оптимизацию процессов и автоматизацию склада, как кажется, невозможно завершить. Она длится в компании уже 5 лет, и, как я сказал выше, даже после 9 этапа мы не собираемся останавливаться. Компания продолжает расширяться и в B2C, и в B2B, так что уже в ближайшем будущем у нас планируется очередной большой проект — открытие еще одного склада, это потребует либо масштабного переписывания существующей системы, либо создания аналогичной с нуля на новом месте. И это новый интересный челлендж на стыке бизнеса, физических объектов, операционных процессов и технических решений.
Автор: asm0dey