Логистика · микросервисы

Логистическая платформа: ключевые процессы с 16 часов до 9 минут

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

  • 8 сервисов за одним шлюзом
  • LDAP + JWT
  • Логи в Elasticsearch
  • ДоменАвтоматизация логистических операций: приём данных, обработка этапов, результат в рабочей панели оператора.
  • СистемаВосемь масштабируемых микросервисов за централизованным API-шлюзом, HTTPS через Nginx.
  • ПанельNuxt 3 и TypeScript, табличный ввод на Handsontable — привычная сетка вместо формы на сорок полей.
  • РольАрхитектура, backend на Go, схема MS SQL Server и миграции, логирование и CI.
16 ч → 9 минобработка ключевых процессов
8масштабируемых микросервисов
1 шлюзцентрализованный вход и авторизация
MS SQLисточник данных и версионированные миграции

Контекст и задача

Процесс, который занимал рабочие сутки

Обработка ключевых операций занимала больше шестнадцати часов. Это не только долго — это ещё и непредсказуемо: пока цепочка идёт, никто не может сказать, на каком она шаге.

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

Отдельная сложность — интерфейс. Операторы работают с данными в табличном виде и сравнивают их построчно; форма с полями по одному значению для такой работы бесполезна, а выгрузка в Excel возвращает нас к тому, с чего начали: данные снова живут вне системы.

Третье ограничение — корпоративный контур. Учётные записи уже есть в LDAP, заводить второй список пользователей никто не будет, а доступ к сервисам должен проверяться в одном месте, а не в восьми.

Задача формулировалась так:

  • разложить процесс на этапы, у каждого из которых есть владелец, контракт и собственный запас по нагрузке;
  • убрать ручные переносы данных между этапами — они и создают основную часть времени ожидания;
  • дать оператору интерфейс, в котором работают с таблицей, а не с формой;
  • подключить аутентификацию к уже существующему LDAP и проверять доступ в единой точке;
  • сделать происходящее видимым: без общего журнала распределённая система превращается в чёрный ящик из восьми частей.

Решение

Пять решений, которые сократили сутки до девяти минут

Микросервисы здесь не самоцель, а способ дать каждому этапу собственный темп изменений и собственное масштабирование.

  1. 01Восемь сервисов вместо одной цепочки. Каждый этап обработки стал отдельным сервисом на Go со своей зоной ответственности и своим контрактом. Этапы, которые не зависят друг от друга, перестали ждать в очереди, а тяжёлый шаг масштабируется отдельно, не утаскивая за собой остальные семь.
  2. 02Централизованный API-шлюз. Наружу торчит один адрес: шлюз маршрутизирует запросы, проверяет доступ и терминирует HTTPS через Nginx. Клиент не знает внутреннюю топологию, поэтому сервис можно разделить или переименовать, не трогая ни панель, ни смежные системы.
  3. 03LDAP + JWT. Учётные записи остаются в корпоративном каталоге, второй список пользователей не заводится. Шлюз проверяет учётные данные в LDAP и выдаёт JWT, дальше сервисы работают с токеном — проверка прав сосредоточена в одном месте, а не размазана по восьми кодовым базам.
  4. 04MS SQL Server и версионированные миграции. Схема меняется вместе с кодом: каждая правка оформлена миграцией с номером, поэтому окружение поднимается до нужной версии одной командой, а не восстановлением из чьей-то резервной копии. Расхождение схем между стендами перестаёт быть отдельным жанром отладки.
  5. 05Панель на Nuxt 3 и наблюдаемость. Интерфейс — Nuxt 3 с TypeScript, табличный ввод на Handsontable: привычная сетка с валидацией и сервером за спиной. Логи всех сервисов собирает Vector и складывает в Elasticsearch, поэтому цепочка обработки читается целиком, а не по фрагментам из восьми контейнеров. Сборка и выкладка — GitLab CI.

ADR · почему микросервисы, а не один процесс

Контекст. Этапы обработки с разным профилем нагрузки и разным темпом изменений; узкое место — один из них, а не все сразу. Решение. Восемь сервисов за централизованным шлюзом, аутентификация и маршрутизация вынесены на вход. Следствие. Масштабируется тот сервис, которому тяжело. Цена — распределённая система, поэтому централизованные логи и единая точка авторизации не «когда-нибудь потом», а часть первой поставки.

Архитектура

Как это устроено

Панель и внешние клиенты видят один шлюз. За ним — восемь сервисов на Go, общий MS SQL Server и отдельный контур наблюдаемости: логи собираются Vector и уходят в Elasticsearch.

  • Go
  • Nuxt 3
  • TypeScript
  • Handsontable
  • MS SQL Server
  • Версионированные миграции
  • LDAP
  • JWT
  • Nginx · HTTPS
  • Vector
  • Elasticsearch
  • GitLab CI
logistics / service-map
Панель Nuxt 3 → API-шлюз с LDAP + JWT → восемь сервисов на Go → MS SQL Server; логи через Vector в Elasticsearch

Результат

Что изменилось

Главный эффект — не в скорости отдельного шага, а в том, что из процесса ушло ожидание.

Девять минут вместо шестнадцати часов

Обработка ключевых процессов перестала занимать рабочие сутки. Результат стал доступен в тот же час, когда пришли данные, а не на следующий день.

16+ ч → 9 мин

Восемь сервисов, которые растут по отдельности

Нагрузка редко распределяется равномерно. Отдельные процессы позволяют добавить мощности там, где узко, не выкатывая заново всю систему.

8 микросервисов на Go

Один вход и одна аутентификация

Учётные записи остались в LDAP, доступ проверяется на шлюзе и подтверждается JWT. Внутренняя топология не протекает наружу и меняется без согласований с клиентами.

Шлюз · LDAP + JWT · Nginx

Видимая цепочка обработки

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

Vector → Elasticsearch

Роль maincode

Что делали мы

В проекте важно различать инженерную часть и предметную: вторая всегда остаётся на стороне заказчика.

  • АрхитектураРазбиение процесса на восемь сервисов, границы ответственности, контур централизованного API-шлюза и схема аутентификации.
  • BackendСервисы на Go: обработка этапов, взаимодействие через шлюз, обработка ошибок и повторов на границах.
  • ДанныеСхема MS SQL Server, индексы под операционные выборки, версионированные миграции для всех стендов.
  • ИнтерфейсРабочая панель на Nuxt 3 и TypeScript с табличным вводом на Handsontable.
  • ЭксплуатацияЦентрализованное логирование Vector → Elasticsearch, публикация через Nginx по HTTPS, сборка и выкладка в GitLab CI.
  • ГраницыПредметные правила и бизнес-показатели остаются у заказчика — в кейсе только инженерная часть и измеренный результат.

Что применили

Услуги, из которых собран этот проект

Если ваша задача другая — посмотрите разбор мультиарендной ERP или движок распределения товара. Полный список — на странице проектов.

Похожая задача?

Расскажите, где у вас копится ожидание — разберём процесс и предложим архитектуру.

Смотрим на этапы, ручные переносы данных и точки, в которых процесс останавливается. Возвращаемся с границами сервисов и планом реализации. maincode — инженерная студия ИП Диденко М. С.