Перейти к содержимому

Расписание обменов - частота, окна, конфликты, блокировка

Расставляем обмены во времени: разная частота для каталога, цен и заказов, ночные окна для полной выгрузки и защита от одновременного запуска.

Что нужно знать заранее

Расписание задаёт учётная система, а не сайт. Сайт лишь принимает запросы, и все разговоры о частоте обмена ведут с тем, кто настраивает выгрузку на другой стороне.

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

Два одновременных обмена почти всегда означают беду. Они соревнуются за одни и те же товары и оставляют каталог в состоянии, которое потом разбирают руками по журналам.

Шаги

  1. Разделить обмены по типам данных и назначить каждому свою частоту.
  2. Договориться о ночном окне для полной выгрузки каталога и предложений.
  3. Поставить защиту от одновременного запуска двух обменов на стороне сайта.
  4. Предусмотреть паузу обмена на время выкладки кода и резервного копирования.
  5. Следить за фактической частотой по журналу и сверять её с договорённостью.

Решение

Смотрим фактическую частоту обменов:

Окно терминала
grep '1c_exchange.php' /var/log/nginx/access.log \
| awk '{print substr($4,2,14)}' | sort | uniq -c | tail -20
# видно и часы активности, и число обращений в каждый из них

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

Смотрим время последнего успешного обмена:

$last = (int)\Bitrix\Main\Config\Option::get('vendor.module', 'last_exchange_ts', 0);
printf("последний успешный обмен: %s\n", $last ? date('d.m.Y H:i', $last) : 'не было');
// метку ставит сам обмен после успешного завершения шага импорта

Закрываем гонку двух обменов:

$lock = \Bitrix\Main\Application::getConnection()->lock('exchange_catalog', 5);
if (!$lock) {
die("failure\nобмен уже выполняется\n"); // вторая сессия уходит ни с чем
}
// блокировку снимают в конце шага, иначе следующий обмен не начнётся вовсе

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

Ставим обмен на паузу перед выкладкой:

\Bitrix\Main\Config\Option::set('vendor.module', 'exchange_paused', 'Y');
// в начале точки обмена: if (пауза) { die("failure\nобмен приостановлен\n"); }
// после выкладки паузу снимают, а учётная система повторит выгрузку сама

Сверяем расписание с нагрузкой сайта:

Окно терминала
grep '1c_exchange.php' /var/log/nginx/access.log | awk '{print substr($4,14,2)}' \
| sort | uniq -c | sort -rn | head -5
grep -c ' 200 ' /var/log/nginx/access.log
# полная выгрузка в час пик замедляет витрину и растягивает сам обмен

Типичные проблемы

Каталог после обмена в непонятном состоянии.

Два обмена шли одновременно и переписывали одни и те же товары. На стороне сайта ставят блокировку, отдающую отказ второму обмену.

Витрина заметно тормозит каждый день в одно время.

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

Обмен упал во время выкладки нового кода.

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

Заказы приходят в учётную систему с задержкой в сутки.

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

Обмен перестал приходить, и никто этого не заметил.

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

Частые вопросы

Кто задаёт расписание обмена?

Учётная система: она инициирует обмен, а сайт только принимает запросы. Поэтому частоту согласуют с тем, кто настраивает выгрузку на её стороне.

Как часто обменивать цены и остатки?

Обычно каждые пятнадцать-тридцать минут, если объём это позволяет. Каталог целиком при этом достаточно выгружать раз в сутки ночью.

Что делать, если обмен идёт дольше окна?

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

Как остановить обмен на время работ?

Флагом на стороне сайта, который отдаёт отказ в начале обмена. Учётная система повторит выгрузку по расписанию после снятия флага.

Нужна ли блокировка, если обмен один?

Нужна: повторный запуск случается при ручном обмене и при зависшем сеансе. Блокировка стоит одну строку и снимает целый класс проблем.

Смежное

Первоисточник