При выполнении длительных и объемных обменов данными (например, при полной выгрузке каталога товаров из 1С в 1С-Битрикс) разработчики часто сталкиваются с крайне неприятной проблемой: регламентное задание внезапно прекращает работу через полчаса или несколько часов после запуска. При этом в стандартном Журнале регистрации (ЖР) нет абсолютно никаких записей об ошибках — задание просто переходит в статус «Выполнено» или прерывается без объяснения причин. В технологическом журнале (ТЖ) при этом обычно фиксируется системное событие excp с сообщением «Требуется переустановка соединения» (Connection Reset).
В этой статье мы подробно разберем, почему происходят такие «тихие» падения фоновых процессов, как функционирует кластер серверов 1С при критических нагрузках и какие конкретные шаги необходимо предпринять, чтобы успешно завершить выгрузку даже полутора миллионов позиций номенклатуры.
Для начала проанализируем внутренние механизмы платформы «1С:Предприятие». Когда мы запускаем любое регламентное или фоновое задание, сервер выделяет под него поток внутри одного из рабочих процессов rphost.exe. Если в коде конфигурации происходит классическая программная ошибка (например, деление на ноль или обращение к несуществующему реквизиту), платформа перехватывает это исключение, корректно останавливает выполнение кода и записывает ошибку в Журнал регистрации.
Однако в случае сбоя при длительном обмене происходит совершенно другой сценарий — аварийное завершение (краш) самого процесса rphost.exe на уровне операционной системы. Причины этого могут быть следующими:
rmngr.exe) или сама операционная система принудительно «убивает» данный рабочий процесс.Когда процесс rphost.exe мгновенно уничтожается, сеансы обычных пользователей могут автоматически и незаметно для них мигрировать на другие, «живые» рабочие процессы кластера. Но активные фоновые задания бесшовно мигрировать не умеют. Выполнявшийся поток обмена просто уничтожается вместе с упавшим процессом. Так как управляющий код платформы в этот момент физически прекратил свое существование, система просто не успевает сформировать и записать лог ошибки в Журнал регистрации.
Выясним, какие системные факторы провоцируют падение рабочих процессов во время выполнения тяжелых регламентных заданий:
0. На многих версиях платформы это трактуется системой не как «без ограничений», а как скрытый лимит (например, жесткий процент от общего объема ОЗУ сервера). При превышении этого порога процесс отправляется на перезапуск.rphost.exe физически не сможет адресовать более 4 ГБ оперативной памяти. На практике падение из-за нехватки памяти (Out of Memory) происходит уже при достижении 3–3.5 ГБ.rphost.exe.DOMDocument (вместо последовательной записи через ЗаписьXML), потребление памяти растет лавинообразно и прямо пропорционально количеству выгружаемой номенклатуры.Б_ПакетныйОбмен). Если база данных развернута на СУБД MSSQL Express, размер которой строго ограничен 10 ГБ, выгрузка гарантированно аварийно завершится при достижении этого лимита файлом базы или транзакций.Рассмотрим комплекс мер, который позволит стабилизировать работу регламентного задания и успешно завершить передачу данных на сайт.
Самый эффективный способ предотвратить утечку памяти и падение процесса — уменьшить объем единовременно обрабатываемых данных. Нам необходимо разбить одну гигантскую транзакцию на множество мелких и безопасных шагов:
Проанализируем параметры нашего кластера через консоль администрирования 1С:Предприятия:
0, попробуйте явно указать безопасное значение в байтах (например, 80-90% от физической памяти сервера, разделенное на количество рабочих процессов), чтобы предотвратить ложные срабатывания механизма защиты от утечек памяти.Поскольку накопленный кэш и незавершенные пакеты обмена могут блокировать работу новых сессий, выполним профилактические работы:
dbgs и каталоги формата reg_XXXX в каталоге службы сервера).РегистрСведений.Б_ПакетныйОбмен), в которых могли зависнуть недописанные куски XML-файлов предыдущих неудачных попыток.Если вы дорабатываете модуль обмена самостоятельно, крайне важно отказаться от монолитного выполнения алгоритма. Реализуйте механизм «точек сохранения» (чекпоинтов) в коде фонового задания. При аварийном завершении процесса и последующем автоматическом перезапуске регламентного задания выгрузка должна продолжаться с того места, на котором она прервалась, а не начинаться заново.
Посмотрим на пример реализации пакетной обработки данных с фиксацией промежуточного прогресса в информационной базе:
// Пример процедуры регламентного задания с фиксацией точек сохранения
Процедура ВыполнитьПакетнуюВыгрузкуНоменклатуры() Экспорт
РазмерПорции = 1000; // Ограничиваем порцию данных для одной транзакции
ПоследнийОбработанныйID = ПолучитьПоследнийУспешныйID();
Пока Истина Цикл
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ ПЕРВЫЕ " + Формат(РазмерПорции, "ЧГ=0") + "
| Номенклатура.Ссылка КАК Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Ссылка > &ПоследнийID
| И НЕ Номенклатура.ЭтоГруппа
|УПОРЯДОЧИТЬ ПО
| Ссылка";
Запрос.УстановитьПараметр("ПоследнийID", ПоследнийОбработанныйID);
РезультатЗапроса = Запрос.Выполнить();
Если РезультатЗапроса.Пустой() Тогда
// Все данные успешно обработаны, сбрасываем точку сохранения
СброситьТочкуСохранения();
Прервать;
КонецЕсли;
Выборка = РезультатЗапроса.Выбрать();
НачатьТранзакцию();
Попытка
Пока Выборка.Следующий() Цикл
// Выполняем экспорт конкретной позиции номенклатуры на сайт или в файл
ЭкспортироватьПозициюНоменклатуры(Выборка.Ссылка);
ПоследнийОбработанныйID = Выборка.Ссылка;
КонецЦикла;
// Фиксируем прогресс в регистре сведений или константе вне транзакции обмена
ЗаписатьТочкуСохранения(ПоследнийОбработанныйID);
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
// Записываем системную ошибку в журнал, если платформа еще работоспособна
ЗаписатьВЖурналРегистрации(
"ОбменБитрикс.Ошибка",
УровеньЖурналаРегистрации.Ошибка,
,
,
"Произошел сбой при обработке пакета. Текст ошибки: " + ОписаниеОшибки()
);
ВызватьИсключение; // Прерываем работу для перезапуска планировщиком
КонецПопытки;
// Принудительно очищаем неиспользуемую память и временные переменные
ОчиститьКоллекциюЭлементов();
КонецЦикла;
КонецПроцедуры
Использование предложенного паттерна гарантирует, что даже если рабочий процесс сервера упадет по независящим от вас причинам, при следующем запуске по расписанию регламентное задание продолжит работу с прерванного места. Это полностью исключит бесконечный цикл выгрузки одних и тех же стартовых пакетов данных.