Журнал обмена обрывается на середине каталога. Последняя строка — обычная рабочая запись, за ней тишина: ни сообщения об успехе, ни сообщения об ошибке. В 1С обмен выглядит прерванным, в административной части магазина часть товаров с новыми ценами, часть со старыми. Рука тянется к самому очевидному действию: запустить всё заново. Иногда это действительно правильный ход, но чаще сначала нужно понять, что именно уже случилось с каталогом, потому что «заново» не означает «с чистого листа».

Эта статья о том, как устроить длительный обмен 1С-Битрикс на отдельном VPS так, чтобы обрыв был событием понятным и разбираемым, а не загадкой. Мы разложим обмен на этапы, посмотрим, что на самом деле означают статусы, выясним, какие ограничения относятся к какому этапу, разберём повтор после разрыва и подумаем о покупателе, который открывает сайт в момент, когда каталог обновлён наполовину.

Три разных события под одним словом «обмен»

Слово «обмен» прячет как минимум три события, и у каждого свой способ сломаться. Сначала данные принимаются: файл или несколько файлов доезжают до сервера. Затем они подготавливаются: архив распаковывается, структура читается, подготавливается всё, что нужно для обработки. Наконец данные применяются к каталогу: товары создаются, обновляются, получают цены, остатки и свойства.

Документация 1С-Битрикс о выгрузке данных на сайт описывает обмен как последовательность стадий и прямо разделяет две из них: успешная доставка файла и завершение его обработки — не одно и то же. Это простое утверждение имеет важное следствие. Сообщение «файл принят» говорит только о первом событии. О том, что каталог изменён, оно не говорит ничего.

Почему это так важно, видно по тому, где эти события происходят. Приём — работа веб-сервера и сети: нужны открытое соединение, место на диске и согласие по размеру передаваемого. Подготовка — работа с файловой системой и памятью. Применение — работа PHP-кода, базы данных и диска под нагрузкой записи. Один и тот же обрыв означает разное в зависимости от стадии. Если связь порвалась на приёме, каталог не тронут вовсе. Если обработка остановилась на применении, каталог находится в промежуточном состоянии, и вот это состояние нам и нужно научиться читать.

Согласование условий в начале

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

Из этого следует практический вывод, который редко озвучивают: ограничение размера — не неприятность, с которой надо бороться увеличением значения, а параметр, по которому 1С подстраивает порции. Сервер называет цифру, и поставка подгоняется под неё. Поэтому вопрос «какой размер выставить» — это вопрос о том, какую порцию ваш сервер надёжно проглатывает за один запрос, а не о том, как бы пропихнуть всю выгрузку целиком.

Идентификатор сессии тоже заслуживает внимания. Он связывает последовательность запросов в один обмен. Для расследований это ценная нить: если в журнале у каждого запроса виден идентификатор сессии, вы можете отделить события одного обмена от соседних. Если вашей настройкой журнал ведётся без него, добавьте его в собственные заметки об обмене: потом это сэкономит часы.

Что на самом деле означает «progress»

На этапе импорта сервер отвечает одним из трёх слов: progress, success или failure. Progress означает, что работа идёт и шаг нужно повторить, чтобы продолжить. Success означает, что импорт данного файла завершён. Failure означает, что произошла ошибка. Документация отдельно подчёркивает: отсутствие ответа успехом не считается. Это самое важное правило во всей схеме, потому что обрыв чаще всего выглядит именно как молчание.

Представьте сторону 1С, которая отправила очередной запрос на импорт и не дождалась ответа: истёк тайм-аут клиента, оборвалось соединение, веб-сервер закрыл запрос. Что известно? Только то, что подтверждения нет. Сервер мог успеть обработать порцию и не успеть ответить. Мог не начать. Мог остановиться на середине. Три разные реальности, один и тот же вид со стороны 1С.

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

Что доказывает каждый признак обмена
ПризнакЧто он подтверждаетЧего он не подтверждает
Файл доставлен на серверДанные лежат на сервереЧто хоть одна запись каталога изменилась
Ответ progressОбработка идёт, шаг не последнийСколько записей применено к моменту ответа
Ответ success по файлуИмпорт этого файла завершёнЧто завершена вся поставка, если файлов несколько
Ответ failureОшибка зафиксированаЧто изменений до ошибки не было
ТишинаПодтверждения нетНи успеха, ни провала

Последние две строки стоит перечитать. Failure не означает «ничего не изменилось»: ошибка могла случиться на сороковой порции из шестидесяти, и тридцать девять уже применены. А тишина — не отказ, а неопределённость, и именно с неопределённостью нужно уметь работать.

Журнал, который отвечает на вопросы

Вывод для практики такой: журнал обмена должен позволять ответить на четыре вопроса без догадок. Какая поставка шла? До какого файла и до какой порции дошла обработка? Каким был последний ответ сервера? Когда он был получен? Если из вашего журнала это не следует, вы не сможете отличить «остановилось» от «ещё работает» и «доработало, но не ответило».

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

Лимиты как условия конкретного этапа

Теперь про ограничения. Привычная реакция на обрыв — «увеличим тайм-аут». Но тайм-аут не одно число, а несколько разных пределов, и каждый действует на своём этапе.

  • Размер принимаемых файлов. Относится к приёму. Это то самое значение, которое сервер сообщает при инициализации. Если оно меньше реального размера части поставки, проблема возникнет ещё до обработки.
  • Время ответа веб-сервера на запрос. Относится к тому, сколько одна порция импорта может выполняться, прежде чем соединение будет закрыто. Для этапа применения это решающее условие.
  • Предел времени выполнения PHP-скрипта. Тоже относится к применению: скрипт, не уложившийся в предел, будет остановлен на середине порции.
  • Память, доступная скрипту. Влияет на подготовку и применение: чтение крупного файла структуры способно упереться именно в неё.

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

Почему бесконечный тайм-аут — плохой ответ

Допустим, вы подняли пределы так, чтобы один запрос мог работать сколь угодно долго. Что вы получили? Во-первых, пропала граница, по которой вы отличали зависание от работы. Запрос, который идёт двадцать минут, может быть и честным трудом, и бесконечным циклом, а различить их вы уже не можете. Во-вторых, длинный запрос держит ресурсы сервера: процесс, память, соединение с базой. Несколько таких запросов, наложившихся друг на друга, мешают и обмену, и обычным посетителям. В-третьих, чем длиннее одна операция, тем больше потеряется при её обрыве и тем дольше придётся выяснять, что успело произойти.

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

Что здесь даёт отдельный VPS

Обмен с 1С — нагрузка своеобразная: редкая, но тяжёлая. Большую часть суток каталог читают покупатели, а в моменты обмена добавляется интенсивная запись, чтение файлов и работа с базой. На общем хостинге вы почти не управляете пределами веб-сервера и PHP и делите ресурсы с соседями. На VPS есть root-доступ, и вы сами выбираете, как настроить пределы под каждый этап, и можете разделять время обмена и пик посещаемости.

Диск здесь тоже участвует: архив нужно принять, распаковать и прочитать, а база записывает изменения. Быстрый накопитель сокращает время каждой порции, а значит, и вероятность не уложиться в лимиты. У VPS MAATRIX это NVMe, процессоры AMD EPYC, а тарифная линейка начинается с конфигурации 1 vCPU, 2 ГБ RAM и 40 ГБ NVMe (Ba) и доходит до 16 vCPU, 32 ГБ и 320 ГБ (Djed); промежуточные ступени — Uab, Heka и Maat. Это перечень ресурсов, а не обещание производительности: сколько товаров и как быстро вы обработаете на конкретной конфигурации, показывают только замеры на вашем каталоге. Подробнее о том, как выбирать сервер под магазин на Битриксе, рассказано в материале VPS для 1С-Битрикс.

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

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации Россия, США, Франция и Великобритания. Оплата картой РФ и по СБП.

АРЕНДОВАТЬ СЕРВЕР

Повтор после обрыва: как не сделать всё дважды

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

Разберём варианты по стадиям, на которых мог произойти разрыв.

Обрыв при передаче файла

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

Тишина во время импорта

Самый неприятный случай. Ответа нет, и по правилу из документации это не успех. Но и провалом это не объявлено. Сервер мог закончить порцию, мог остановиться посередине. Здесь действует осторожная последовательность: сначала выяснить по журналу сервера, что произошло с последним запросом, и только потом возобновлять. Журнал веб-сервера покажет, получен ли запрос и чем он завершился. Журнал обмена — до какой порции дошла работа.

Если порция была применена, а ответ потерялся, повтор того же шага может применить её второй раз. Будет ли это вредно, зависит от природы изменения. Присвоение товару цены повторно даёт тот же результат: цена стала такой, какой была. Прибавление количества к остатку повторно даёт уже другой результат. Различие между «установить значение» и «изменить значение» — ключ ко всему вопросу безопасного повтора.

Ответ failure

Ошибка зафиксирована явно, и это, как ни странно, лучшее из плохих сообщений: вы хотя бы знаете, что остановка случилась. Но не стоит читать его как «откатилось всё». До ошибки часть порций могла быть применена. Поэтому и здесь сначала смотрим, что именно изменено, и лишь затем решаем, продолжать ли с места остановки или запускать поставку заново.

Возобновление и идентификатор поставки

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

Практическое правило на основе этих рассуждений: у каждой поставки должен быть собственный устойчивый идентификатор, связанный с её содержимым. Он нужен не для того, чтобы обмен волшебно стал идемпотентным, а для того, чтобы вы могли ответить на вопрос: «Это та же поставка, что была прервана, или уже другая?» Если вы повторяете ту же поставку, вы знаете, какие порции в ней уже подтверждены. Если запускается новая выгрузка с обновлёнными данными, это другой идентификатор и другой разговор.

В самой процедуре повтора можно придерживаться такой последовательности:

  1. Остановить автоматические запуски обмена, чтобы новый запуск не наложился на разбираемый.
  2. Найти в журнале последний подтверждённый шаг данной поставки и последний отправленный запрос.
  3. По журналу веб-сервера выяснить, чем закончился этот запрос.
  4. Определить, какие порции с подтверждённым применением, какие без подтверждения.
  5. Для сомнительной порции проверить на конкретных записях, применена ли она.
  6. Только после этого возобновлять или перезапускать обмен.

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

Каталог на полпути: что видит покупатель

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

Обрыв превращает этот интервал из короткого в неопределённый. Если обмен упал и никто не заметил, половина каталога может жить на старых данных до следующей выгрузки. Покупатель оформит заказ по цене, которой в 1С уже нет, или по остатку, который давно продан.

Деактивация при полной выгрузке

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

Вместе с этой логикой приходят два практических вопроса. Первый: что станет, если обмен оборвался и успешной выгрузки не было? Из описанного порядка следует, что деактивация привязана к успешному завершению, поэтому при незавершённом обмене её ожидать не стоит. Но уверенность в том, как именно это работает в вашей версии и интеграции, дает только проверка. Второй, более коварный: что произойдёт, если выгрузка формально завершилась успешно, но оказалась неполной по содержанию? Например, на стороне 1С отбор по каким-то причинам исключил часть номенклатуры. С точки зрения механизма всё прошло правильно, а невыгруженные товары будут деактивированы, и из магазина исчезнет часть ассортимента.

Это та ситуация, где слово «success» не снимает ответственности: оно говорит, что механизм отработал, а не что содержимое поставки было тем, что вы хотели. Именно поэтому на копии стоит проверить, как ведёт себя деактивация, до того как она случится в боевом магазине.

Репетиция на копии

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

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

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

Когда репетицию делают на VPS, удобно, что сервер создаётся быстро: в публичном предложении MAATRIX указано автоматическое создание после оплаты за пару минут, доступны карта РФ и СБП, а локации перечислены: UK, US, RU и FR. Для работы с российскими данными и обменом с 1С практичнее выбирать расположение исходя из ваших требований и сетевых условий; точное наличие образов и локаций проверяйте в форме заказа.

Защита от молчаливого расхождения

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

Первая — различать приём, подготовку и применение в собственных записях. Вместо общего «обмен прошёл» ведите три отметки: поставка получена, поставка подготовлена, применены такие-то порции из стольких-то.

Вторая — не принимать тишину за результат. Если ответа нет, ожидание заканчивается не фразой «наверное, получилось», а проверкой по журналам. Автоматический повтор без выяснения причин годится лишь там, где вы заранее убедились, что повтор безопасен.

Третья — держать порции короткими, а пределы PHP и веб-сервера настроенными осмысленно, а не максимальными. Вместо поиска значения, при котором «больше не падает», ищите порцию, которая стабильно укладывается с запасом. Запас нужен потому, что в день, когда в выгрузке окажется больше изменений, чем обычно, обмен не должен упасть из-за этого.

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

Сверка вместо сообщения «обмен завершён»

Финальный вопрос после любого обмена, особенно прерванного и повторённого: как убедиться, что магазин соответствует поставке? Сообщение «обмен завершён» отвечает лишь на вопрос, закончил ли механизм работу. А нас интересует результат.

Сверку удобно строить вокруг двух опор: идентификатор поставки и её содержимое. Идентификатор отвечает на вопрос «о какой именно поставке мы говорим», содержимое — «что в ней должно было оказаться на сайте».

Возьмём условный пример: поставка из 12 000 позиций, передаваемая порциями. Допустим, обмен оборвался, вы разобрались, повторили, и журнал показывает успех. Сверка выглядит так.

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

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

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