Ускоряем обмен остатками с помощью новой функции модуля обмена

В этой статье рассмотрим:

  • Принцип работы новой функции "**Быстрые остатки**", которая появилась в модуле **МойСклад: Синхронизация товаров по API**.
  • Посмотрим на отличия двух типов импорта остатков их плюсы и минусы.
  • Протестируем работу функции на каталоге размером 15 000 товаров с 5-ю складами.
В Moysklad  JSON API 1.2 есть два способа считывания остатков по складам:

  1. Расширенный отчет (вкладка "Остатки" в модуле)**. Остатки считываются все подряд без возможности получить только измененные данные по остаткам. Считывание происходит пошагово, максимально 1000 позиций за 1 шаг.
  2. Текущие остатки (вкладка "Быстрые остатки" в модуле)**. Остатки считываются либо все подряд (без пошаговости), либо только измененные с определенного времени.
Сокращения в статье:
  • МойСклад = МС
  • База данных = БД
Опишем каждый из способов подробнее.

[spoiler]
Способ обмена 1. Расширенный отчет (вкладка "Остатки" в модуле)

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

Если у вас небольшой или средний каталог товаров (до 10 000 товаров), то вам вполне подойдет этот способ обмена, т.к. скорость считывания остатков здесь распределяется достаточно равномерно и предсказуемо, при этом нагрузка на каждый шаг импорта будет не высокой.

Примерный импорт всех остатков будет равен полному кругу прохождения модулем по позициям.

Например, у вас имеются:
- Каталог на 5 000 позиций (товары + модификации)
- 5 обмениваемых складов

При таких вводных, скорость обмена будет примерно следующая:

5000 товаров / 1000 товаров за шаг = 5 шагов
5 шагов * 120 секунд = 600 секунд = 10 минут
В этом способе количество складов будет влиять только на скорость записи остатков в БД. Чем больше складов, тем больше позиций остатков нужно будет записать модулю на каждом шаге. Сами значения остатков сверяются модулем, поэтому запись \ добавление остатков происходит только при их изменении, но сравнение значений происходит постоянно.

Ниже рассмотрим что такое позиция остатка, но стоит заметить что даже при небольшом каталоге и большом количестве складов, сам расширенный отчет в МС может формироваться долго, другими словами модуль может ожидать от API МС долгий ответ, что может привести к разрыву соединения, таким образом отчет для модуля может и вовсе не сформироваться (подробнее описано ниже в минусах текущего способа).

У этого способа есть 2 плюса:

  1. Можно фильтровать позиции для считывания остатков по доп. полю или группе товаров. Это даст возможность сократить количество шагов для обновления всех остатков, т.к. импортировать остатки можно только для отфильтрованных товаров.
  2. Можно использовать функционал суммирования дочерних складов. В МС склады могут быть представлены в виде иерархии, где родительский склады могут быть нулевыми по факту, но модуль умеет суммировать остатки дочерних складов и получать актуальный остаток для родительского склада.

И есть 1 минус:

Если у вас большой каталог (более 5 000 или более 5 складов), то сам МС может очень долго формировать отчет и модуль может не дождаться ответа от сервера, т.к. ему дается всего 60 секунд на ожидание ответа. При любом запросе этого отчета, МС может долго формировать сам отчет и модуль может его не дождаться, тем самым он не сможет обновить остатки на сайте. Формирование отчета напрямую зависит от загруженности вашего аккаунта МС документами оприходования \ списания \ заказов покупателя и т.п. Чем больше документов влияющих на остатки, тем дольше формируется расширенный отчет остатков.

Способ обмена 2. Текущие остатки (вкладка "Быстрые остатки" в модуле)

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

  1. Нет возможности фильтровать позиции для отчета по группе / доп. полю.
  2. Нет возможности использовать функционал дочерних складов (может быть устранен в одном из обновлений модуля).
  3. Нет возможности импортировать остатки для комплектов (может быть устранен в одном из обновлений модуля).
  4. На обновление всей таблицы потребуется больше времени чем обычно при работе функции (таблица обновляется вся раз в сутки).
Первый минус нивелируется тем, что скорости обмена хватает, чтобы загружать все остатки из МС достаточно быстро. Второй и третий минусы будут устранены в одном из обновлении модуля.

Плюсы этого способа следующие:

  1. Быстрое формирование всего отчета без необходимости пошагово загружать данные из самого МС.
  2. Есть возможность обновлять только измененные данные, что ускоряет обмен остатками до скорости вызова самой функции импорта быстрых остатков (обычно это раз в 1-2 минуты).
Тест скорости быстрых остатков

*Важное замечание: мы будем тестировать именно отчет "текущие остатки (быстрые остатки в модуле)" на большом каталоге, т.к. расширенный отчет остатков работает достаточно предсказуемо. И нагрузка у него равномерная на каждом шаге работы.

Для тестирования нам нужно сгенерировать товары и оприходования в МС.

Параметры будут следующие:

  1. Генерируем 15 000 простых товаров
  2. Создаем 5 складов
  3. Для каждого товара генерируем остатки на всех 5-ти складах
Итого получаем 15 000 товаров * 5 складов = 75 000 позиций остатков, т.е. столько физически строк в базе данных сайта будет когда мы импортируем все остатки для каждого товара.

Обратите внимание на новое понятие "позиция остатка". Оно нужно для понимания, т.к. присутствует даже в настройках модуля. Как уже описано выше, позиция остатка является физической строкой в БД для остатка 1 товара на 1 складе. Если у товара несколько складов (допустим 5), то позиций остатка для 1 товара будет 5.

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

Этап 1. Генерация товаров.

Для генерации товаров был написан простой скрипт, который создает простые товары в МС.
Создаем 15 000 простых товаров.


Этап 2. Оприходования.

Далее нам нужно каждые из этих 15 000 товаров оприходовать на всех 5-ти используемых складах.

Оприходовать будем по 500 товаров на каждый документ "Оприходование".
Итого получится: 15 000 / 500 = 30 документов оприходования на 1 склад.

Далее 5 складов * 30 документов \ склад = 150 документов оприходования для всех складов и товаров.

Сами значения остатков будут заполнятся случайными числами.



Документов получилось немного больше, т.к. по факту в каталоге более 15 000 товаров, но это не влияет на результаты тестирования.

Этап 3. Импортируем модулем на сайт все товары.

Здесь все просто, воспользуемся функцией разового импорта и получим достаточно быстро все 15 000 позиций на сайте:



На стороне сайта мы получили все товары из МС:



Этап 4. Настройка модуля на импорт быстрых остатков.

Модуль настраиваем так:



Здесь стоит обратить внимание на опцию "Шаг импорта (количество записей остатков)". Эта опция сообщает модулю сколько позиций остатков обрабатывать за 1 шаг импорта. Давайте еще раз вспомним, что позиции остатков НЕ РАВНО количеству товаров. Т.к. одна позиция остатка -- остаток для 1 товара на 1 складе. Если складов будет 5, то для 1 товара будет ровно 5 позиций остатков.

В нашем случае 15 000 товаров * 5 складов = 75 000 позиций остатков.

Если у вас мощный сервер и он способен быстро работать с записью в БД, то можете ставить большее количество обрабатываемых позиций, в нашем эксперименте оставим значение в 1000 позиций остатков.

Исходя из настроек делаем следующие выводы по дальнейшей работе модуля:

  • Первый запрос будет самым "тяжелым" т.к. он обновит всю таблицу кеша быстрых остатков и сразу обработает 1000 позиций остатков
  • Второй и последующие запросы будут "легче", т.к. они будут включать в себя считывание только измененных остатков с момента последнего шага и проверка 1000 позиций остатков.
  • Для первоначального импорта модулю потребуется 75 шагов (75 * 1000 = 75 000 позиций остатков) для того, чтобы остатки заполнились для каждого товара.
Этап 5. Тестирование скорости обмена остатками.

Поскольку тестируемый каталог и остатки были сгенерированы с нуля, то тестирование скорости обмена по факту будет разделено на 2 этапа:
  1. Первичный импорт позиций остатков
  2. Обновление текущих остатков
Первичный импорт будет нагружать БД на запись данных, т.к. данные по остаткам нужно заполнить изначально. Сам этап повторится единожды, далее будет работать только обновление текущих остатков, поэтому скорость актуализации остатков зависит именно от второго этапа.

Первичный импорт позиций остатков

Запустим несколько раз вручную первые несколько шагов импорта, чтобы понимать примерное время выполнение первого и последующих шагов.



Можем заметить, что первый шаг, как и ожидалось был самым тяжелым (103 секунды). Он повторится уже ночью согласно настройкам модуля. Остальные шаги более легкие (по 17 секунд), т.к. пока их задача заключается в заполнении остатками все товары на всех складах. Как только все остатки заполнятся, далее модуль будет просто сверять их значения и скорость обмена будет действительно впечатляющей.

Первый этап будет закончен, когда все 75 000 позиций остатков будут записаны в БД сайта. Поэтому подождем некоторое время пока модуль автоматически прогрузит остатки.

Обновление текущих остатков

После того, как модуль первично прогрузит остатки, далее вызов функции обновления остатков будет моментальным, т.к. изменений по остаткам не будет происходить.



Для имитации изменения остатков, просто удалим рандомный документ оприходования, тогда остатки должны будут изменится для тех товаров, которые будут в этом документе. Посмотрим как быстро данные придут на сайт.


Удалили документ с 500 позициями остатков в 22:19. Ждем изменений на сайте.



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

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

Если бы мы аналогично протестировали изменение остатков у 500 товаров на обычном пошаговом импорте остатков, то ждать бы пришлось пока модуль не пройдет все товары (это 15 шагов по 1000 позиций), только после этого с гарантией бы получили актуальные остатки. Быстрые остатки справились с этим практически моментально.

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

Заключение

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

Протестируйте работу быстрых остатков на своем сайте: http://marketplace.1c-bitrix.ru/solutions/rbs.moyskladstocks/

Сайт разработчика модуля: https://despi.ru