One Ring to rule them all
J. R. R. Tolkien «The Lord of the Rings»
Введение
Все чаще наши клиенты обращаются в ИНТЕРВОЛГУ с запросом на комплексную масштабную работу над проектом. Мы не удивляемся этому: время небольших доработок, «перекрашивания» кнопок и починки страничек прошло.
В последние несколько лет средний и крупный бизнес стремится превратить сайт в многофункциональный инструмент для взаимодействия с партнерами и клиентами. И желательно — единственный инструмент. Все чаще нас просят добавить «пару отчетиков для партнеров», программу лояльности и биллинг прямо на сайте. Позже выясняется, что отчеты — это не SUM и GROUP BY по табличке заказов, а ТЗ на десять страниц с дифурами и прочим матаном, программа лояльности должна учитывать лайки в соцсетях, а биллинг должен быстро работать в реальном времени. Под капотом у таких функций — масштабные вычисления, к которым традиционный веб-сайт просто не готов.
Значительные подсчеты требуются и для интернет-магазинов федерального масштаба. Их отличия от обычного ИМ:
- Работа по всей России: GeoIP, многоскладовость и прочие вытекающие (а не один-два города) 
- Десятки миллионы товаров и SKU, а не десятки тысяч 
- Лихо закрученное, как лента Мебиуса, ценообразование (а не две цены: «Опт», «Розница») 
- Магазин-маркетплейса (продажа чужих товаров с партнерской комиссией) 
- Десятки интеграций с разными учетными системами (и ни одной 1С!) 
И, разумеется, чтобы работало быстро.
Как же сделать тяжелые вычисления вебе и не уронить сервер? За последние 5 лет мы ни раз сталкивались с подобными проектами.

Как увеличить производительность веб вычислений
В обоих случаях (личные кабинеты и федеральные интернет-магазины) требуется быстро оперировать большими объемами данных. Наращивание мощностей веб-сервера помогает до поры до времени. Веб как технология никогда не был сверхскоростной средой для громоздких вычислений. На то есть несколько причин:
- Язык разработки. PHP, Ruby, Python многократно проигрывают компилируемым языкам в производительности. 
- Протокол HTTP. А конкретно — понятие таймаута. Считать на лету слишком долго не получится, рано или поздно серверу нужно будет оборвать соединение и браузер покажет ошибку ожидания ответа. Спасает пошаговое выполнение процедуры, но не всегда. 
- Особенности ПО. Повсеместные apache и nginx успешно справляются с умеренно большим потоком пользователей, если запросы простые и отрабатывают быстро. Отдать 10 000 раз главную страницу — не проблема. А вот вычислить 10 000 балансов на лету уже не так весело. 
Очевидный вариант — переложить тяжелую работу с сайта на учетную систему. УС действительно эффективнее при решении сложных задач, но они не рассчитаны на ту нагрузку, которую создает посещаемый веб-сайт. Получается конфликт: сайт считает медленно, но для тысяч пользователей, а УС — быстро, но для пяти-десяти. У нас был опыт с проектами обоих типов.

Наш вывод — ни одна из этих систем не должна заниматься постоянными тяжелыми вычислениями. Откладываем в сторону бритву Оккама и начинаем проектировать промежуточное ПО (связующее ПО или middleware). Middleware примет на себя основную нагрузку.

Пожелания к middleware:
- Работа на отдельном (от сайта и УС) сервере; 
- Современный, распространенный язык программирования и фреймворк. 
- Надежный подрядчик. 
В простом случае промежуточное ПО можно разработать на базе более упрощенных систем (отдельная копия, разумеется). Но если критична скорость ответа и выживаемость под высокой нагрузкой, лучше написать отдельный софт, например на Java (быстрый и современный язык), которая по скорости не уступает C/C++.
Рассмотрим более сложную задачу. Сколько middleware потребуется для такой инфраструктуры проекта?

Как ни странно, понадобится только один новый узел.

Развитие идеи middleware для большего количества IT-систем называется ESB (enterprise service bus — сервисная шина предприятия). Иногда этот подход называют интеграционной шиной или шиной данных. Как и промежуточное ПО в случае с двумя системами, это не какой-то конкретный продукт или фреймворк, а подход, призывающий совершать все транзакции между IT-системами в единой точке.
Существует паттерн проектирования, реализующий эту же логику с той же целью. Это Медиатор (Mediator). Он выступает посредником между различными классами, предотвращает прямое взаимодействие и способствует ослаблению связей в коде. Элементы системы не знают о существовании друг друга, только о существовании Медиатора. Согласитесь, очень похоже на определение middleware и интеграционной шины?
Но чем же, в таком случае, должны заниматься учетная система и сайт, если всю тяжелую работу выполняет middleware? Сайт становится простой «болванкой»? Не совсем. Мы снимаем с сайта только самые тяжелые операции, для которых он не пригоден по определению. Для всего остального он по прежнему — лучшее решение
- 
Сайт как «фронт»: - выводит чистые данные клиенту, 
- красивый и удобный, 
- собирает пользовательские данные из форм, 
- отправляет письма и СМС (не маркетинговые рассылки, а разовые уведомления), 
- готовит запросы к middleware, 
- выводит вычисленные результаты. 
 
- 
Middleware: - чистит данные от мусора, ( intervolga@gmail.ru -> intervolga@gmail.com ) 
- удаляет то, что невозможно очистить (intervolga@.ru), 
- стандартизирует данные (а в вашей CRM номера клиентов через «+7», «7» или «8»?) 
- сопоставляет товары, статусы, адреса («г. Москва» и «гор. Москва»), 
- ведет учет остатков, 
- взаимодействует с десятком учетных систем, 
- производит инкрементальные расчеты для ускорения типовых запросов. 
 
- 
Учетная система как «бэк»: - биллинг, 
- учет транзакций, 
- расчет баланса, 
- складской учет, 
- вычисление персональных цен. 
 
Кейсы с конкретными задачами
Кейс 1. Отчеты в реальном времени
Задача
Строить отчеты партнеров на сайте
Правильное решение
- Каждый день middleware подводит промежуточный итог за прошедший день для каждого партнера по всем отчетам. 
- Сайт не строит отчеты, только собирает заявки и ставит их в очередь. 
- Из очереди заявки на отчет попадают в middleware, которое и ведет расчеты по своей копии данных из УС. Middleware считает только статистику за сегодняшний день, за предыдущие уже все посчитано. 
- Middleware передает сгенерированные данные в виде готового PDF/DOC/XLS на сайт. 
P.S. Приведенный сценарий хорош если в вашей учетной системе запрещено редактировать первичку задним числом. В противном случае алгоритм усложняется.
Кейс 2. Персональные цены
Задача
На каждый товар B2B интернет-магазина практически у каждого пользователя своя скидка/наценка. Как результат — своя цена. Учетная система писалась чуть ли не во времена СССР, скидки зависят от двадцати параметров и никто не может объяснить, как оно работает.
Правильное решение
- Учетная система выгружает на сайт товары с базовой ценой (максимальная цена без скидок). 
- При открытии страницы сайт отображает базовые цены товаров. По ним же происходит сортировка и фильтрация. Этот результат можно закешировать. 
- Параллельно сайт запрашивает из middleware цены для нужных товаров для текущего пользователя. Сайт отображает цены. 
Кейс 3. Участие в акции компании с филиалами
Задача
В B2B портале производители размещают акции для компаний-дистрибьюторов (купи X товаров по цене Y в количестве Z в каждый магазин и получи бонусы). Пользователи портала — холдинги и дистрибьюторы могут прямо на сайте принять участие в акции. Если холдинг решает принять участие в акции — то в акцию автоматически должны вступить все дочерние компании со всеми магазинами. Но не у всех компаний заключен договор с производителем. Даже если и заключен, в договоре могут быть ограничение на минимальное/максимальное количество товаров, которые компания может купить у производителя.
Задача: при подписке холдинга на акцию подписать все допустимые компании, рассчитать сумму сделки и ожидаемые бонусы за участие в акции.

Правильное решение
- Вся нужная информация для вступления в акцию доступна в middleware. Хороший вариант — master-slave репликация БД (потребуется только чтение и всегда актуальные данные). 
- При вступлении холдинга в акцию сайт добавляет задание в очередь для middleware. 
- Из очереди задания попадают в middleware. Middleware проверяет наличие договоров и их условия, запоминает рассчитанные данные и возвращает результат на сайт (сумма сделки, плановые бонусы). 
- Сайт отображает результат вступления. 
- При изменении состава холдинга или других первичных данных middleware должен пересчитать и обновить ранее запомненные данные. Тогда следующий запрос от сайта выполнится значительное быстрее. 
Кейс 4. Десятки учетных систем
Задача
Для проекта типа «маркетплейс» требуется собирать номенклатуру у десятков (в перспективе — сотен) партнеров и отображать на сайте. Оформленные на сайте заказы отправлять обратно в УС каждого партнера отдельно. Заранее неизвестно, какое ПО будет у партнера и в каком формате будут предоставлены данные о товарах и заказах. Товары у партнеров примерно одинаковые.
Правильное решение

- ESB собирает товары в единую базу и выполняет сопоставление товаров с единым справочником (по артикулам, характеристикам, штрих кодам и т.д.). 
- ESB анализирует цены от разных поставщиков. Если 9 разных партнеров предлагают товар за 10000 рублей, а 10-ый за 100 — возможно, сопоставление произошло некорректно и показывать такой товар на сайте нельзя. 
- ESB готова обмениваться с учетными системами партнеров по самым простым протоколами в ручном режиме. CSV и YML для товаров, CSV и CommerceML 2 для заказов. 
Заключение
Сделать интеграцию нескольких IT-систем можно по-разному. Если вы хотите, чтобы результат был масштабируемым, чтобы увеличение объема данных в два раза не увеличивало тормоза сайта в два раза, обращайтесь к нам. Каждую задачу нужно решать правильными инструментами. 1С для учета и сотрудников. Сайт для UX. Промежуточное ПО для «грязной» работы.
Комментарии (5)
 - SergeKh29.07.2021 19:01- Странный подход. Для работы вашего "middleware" все равно нужна база данных. А база как правило умеет посчитать любые "отчетики" внутренними процедурами быстрее чем любое стороннее ПО. Она сама по себе уже есть предельно оптимизированное и качественно откомпилированное ПО, предназначенное именно для обработки данных. 
 Я так понял у вас одна из проблем что в базу пихается мусор. Ну так это не правильно, мусор чистить при генерации отчетов, мусор надо чистить на этапе занесения его в базу.
 Сторонние программы на компилируемых языках в подобных системах нужны как правило как микросервисы с минимальной латентностью, а не как хост для тяжелых вычислений.
 - GoodGod30.07.2021 10:26+2- Middleware: - чистит данные от мусора, ( intervolga@gmail.ru -> intervolga@gmail.com ) 
- ведет учет остатков, 
- взаимодействует с десятком учетных систем, 
- cтроит отчеты партнеров на сайте 
- middleware хранит цены для нужных товаров для текущего пользователя 
- проверяет наличие договоров и их условия, запоминает рассчитанные данные и возвращает результат на сайт 
- анализирует цены от разных поставщиков 
 - Что вы нам тут рассказываете что вы написали одну мега-систему которая собственно делает вообще всё, что можно сделать. Вы представляете что за гигантский монолит это будет? 
 - HenryPootle30.07.2021 12:22+3- То, что Вы описали - это не ESB. Это именно некое идеальное middleware, которое и швец и жнец и на машинке, мур-р-р, тоже. И, так же как и идеальный муж, не существует. - А ESB нужна ровно для одного - доставить сообщение от одной системы до другой с гарантированным результатом. 
 
           
 
MentalBlood
Для Python можно писать модули, содержащие код на C, например. Он компилируется при установке модуля. Оверхед получается практически нулевой, только на перевод аргументов и возвращаемых значений между форматами Python и C время тратится
werwolflg
На PHP тоже можно писать модули содержащие код на C.