Журнал обмена обрывается на середине каталога. Последняя строка — обычная рабочая запись, за ней тишина: ни сообщения об успехе, ни сообщения об ошибке. В 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С выгружается как снижение цен на группу, и одинаковые товары в разных порциях на время получают разные цены.
Обрыв превращает этот интервал из короткого в неопределённый. Если обмен упал и никто не заметил, половина каталога может жить на старых данных до следующей выгрузки. Покупатель оформит заказ по цене, которой в 1С уже нет, или по остатку, который давно продан.
Деактивация при полной выгрузке
Особое место занимает полная выгрузка. По документации, при ней предусмотрена деактивация товаров, которых в выгрузке не оказалось, и происходит она после успешной выгрузки каталога. Идея понятна: если товара в полной выгрузке нет, значит, в 1С он больше не числится, и на сайте его следует скрыть.
Вместе с этой логикой приходят два практических вопроса. Первый: что станет, если обмен оборвался и успешной выгрузки не было? Из описанного порядка следует, что деактивация привязана к успешному завершению, поэтому при незавершённом обмене её ожидать не стоит. Но уверенность в том, как именно это работает в вашей версии и интеграции, дает только проверка. Второй, более коварный: что произойдёт, если выгрузка формально завершилась успешно, но оказалась неполной по содержанию? Например, на стороне 1С отбор по каким-то причинам исключил часть номенклатуры. С точки зрения механизма всё прошло правильно, а невыгруженные товары будут деактивированы, и из магазина исчезнет часть ассортимента.
Это та ситуация, где слово «success» не снимает ответственности: оно говорит, что механизм отработал, а не что содержимое поставки было тем, что вы хотели. Именно поэтому на копии стоит проверить, как ведёт себя деактивация, до того как она случится в боевом магазине.
Репетиция на копии
Копия магазина на отдельном VPS нужна не для красоты. Она позволяет сделать то, чего нельзя сделать в боевом магазине: намеренно прервать обмен и посмотреть последствия. Корректный сценарий репетиции состоит из нескольких опытов.
- Прервать обмен во время передачи файла и проверить, что каталог не изменён, а повтор проходит без следов недокачанной части.
- Прервать обмен в середине применения и зафиксировать, какие товары обновлены и какие нет, а также что показывает журнал.
- Повторить прерванную поставку и сравнить итоговое состояние с эталонным, полученным при непрерывном обмене. Особенно внимательно смотрите на величины, которые не устанавливаются, а накапливаются.
- Выгрузить заведомо урезанный полный каталог и посмотреть, какие товары будут деактивированы.
Для копии не нужен самый мощный сервер: задача — воспроизвести поведение, а не пиковую нагрузку. Но стоит иметь в виду, что скорость порций на копии с меньшими ресурсами будет другой, и выводы о времени применения на неё переносить нельзя. Выводы о логике — что применяется, что нет, как ведёт себя повтор — переносятся хорошо.
Когда репетицию делают на VPS, удобно, что сервер создаётся быстро: в публичном предложении MAATRIX указано автоматическое создание после оплаты за пару минут, доступны карта РФ и СБП, а локации перечислены: UK, US, RU и FR. Для работы с российскими данными и обменом с 1С практичнее выбирать расположение исходя из ваших требований и сетевых условий; точное наличие образов и локаций проверяйте в форме заказа.
Защита от молчаливого расхождения
Если свести рассуждения к одному принципу, он такой: любое состояние обмена должно быть выводимо из наблюдаемых фактов, а не из предположений. Практически это выливается в несколько привычек.
Первая — различать приём, подготовку и применение в собственных записях. Вместо общего «обмен прошёл» ведите три отметки: поставка получена, поставка подготовлена, применены такие-то порции из стольких-то.
Вторая — не принимать тишину за результат. Если ответа нет, ожидание заканчивается не фразой «наверное, получилось», а проверкой по журналам. Автоматический повтор без выяснения причин годится лишь там, где вы заранее убедились, что повтор безопасен.
Третья — держать порции короткими, а пределы PHP и веб-сервера настроенными осмысленно, а не максимальными. Вместо поиска значения, при котором «больше не падает», ищите порцию, которая стабильно укладывается с запасом. Запас нужен потому, что в день, когда в выгрузке окажется больше изменений, чем обычно, обмен не должен упасть из-за этого.
Четвёртая — разводить обмен и пиковые часы. Если обмен настроен по расписанию, поставьте его на время минимальной посещаемости. Тогда и покупатели реже наткнутся на полуобновлённый каталог, и обмен не будет конкурировать с ними за ресурсы.
Сверка вместо сообщения «обмен завершён»
Финальный вопрос после любого обмена, особенно прерванного и повторённого: как убедиться, что магазин соответствует поставке? Сообщение «обмен завершён» отвечает лишь на вопрос, закончил ли механизм работу. А нас интересует результат.
Сверку удобно строить вокруг двух опор: идентификатор поставки и её содержимое. Идентификатор отвечает на вопрос «о какой именно поставке мы говорим», содержимое — «что в ней должно было оказаться на сайте».
Возьмём условный пример: поставка из 12 000 позиций, передаваемая порциями. Допустим, обмен оборвался, вы разобрались, повторили, и журнал показывает успех. Сверка выглядит так.
- Подтвердите по журналу, что успех относится именно к этой поставке, а не к предыдущей: сошёлся идентификатор.
- Сравните количество позиций в поставке с количеством затронутых записей в магазине. Расхождение — повод искать пропущенные порции.
- Возьмите контрольную выборку: несколько товаров из начала, середины и конца поставки, особенно из порции, на которой случился обрыв. Сравните цены, остатки и признак активности с содержимым поставки.
- Проверьте величины, которые могли быть удвоены повтором: те, что накапливаются, а не устанавливаются.
- Если выгрузка была полной, сверьте список деактивированных товаров с ожиданием: в нём не должно быть позиций, которые в 1С остались живыми.
Контрольная выборка — не прихоть. Начало поставки показывает, что обработка стартовала правильно, конец — что она дошла до финала, а сомнительная порция в середине — что обрыв не оставил дыру. Если все три точки сходятся, а подсчёт совпал, вы вправе говорить, что магазин соответствует этой поставке, и можете подтвердить это не словами механизма, а фактами.
Обрыв обмена перестаёт быть катастрофой, когда вы знаете, что считать подтверждённым, а что нет. Приём файла не равен применению, тишина не равна успеху, а «success» не равен правильному содержимому. Если вести обмен по этим различиям на сервере, где можно спокойно отрепетировать сбой, то вместо вопроса «повторить всё или нет» остаётся рабочий: «какая порция была последней подтверждённой и совпадает ли магазин с поставкой».