При интеграции систем или организации обмена данными с интернет-магазинами разработчики часто настраивают запуск регламентных заданий с высокой частотой — например, каждые 5 секунд. Такая интенсивность позволяет поддерживать актуальность данных в реальном времени, но порождает серьезную проблему: журнал регистрации (ЖР) мгновенно забивается системными событиями старта и успешного завершения фоновых процессов.
За одни сутки регламентное задание с интервалом запуска в 5 секунд создает более 17 000 сеансов фоновых заданий, что генерирует около 34 000 записей в журнале регистрации. Это приводит к стремительному раздуванию базы данных ЖР, деградации производительности СУБД и крайней сложности анализа реальных системных ошибок.
В этой статье мы подробно разберем, можно ли точечно отключить логирование для конкретной регламентной процедуры, как управлять системными событиями журнала регистрации программно и как оптимизировать сам процесс обмена с помощью правильных архитектурных шаблонов.
Начнем с главного платформенного ограничения: в 1С невозможно отключить запись в журнал регистрации для одного конкретного регламентного задания. Настройки ведения журнала регистрации являются глобальными для всей информационной базы. Платформа не предоставляет разработчику инструментов или директив метаданных, позволяющих выборочно игнорировать создание записей типа «Старт фонового задания» или «Завершение фонового задания» для определенной строки расписания.
Тем не менее, решить проблему избыточного логирования и снизить нагрузку на дисковую подсистему можно двумя эффективными способами:
Начиная с версии платформы 1С 8.3.6, у разработчиков появилась возможность управлять составом регистрируемых в ЖР событий программным путем с помощью метода УстановитьИспользованиеСобытияЖурналаРегистрации().
Если бизнес-требования не требуют детального аудита запусков каждого фонового задания, мы можем полностью отключить запись событий старта и успешного завершения фоновых процессов для всей информационной базы.
Проанализируем пример кода для отключения логирования системных событий фоновых заданий:
ИспользованиеСобытия = Новый ИспользованиеСобытияЖурналаРегистрации;
ИспользованиеСобытия.Использование = Ложь;
// Отключаем регистрацию начала выполнения фонового задания
УстановитьИспользованиеСобытияЖурналаРегистрации("_$Job$_.Start", ИспользованиеСобытия);
// Отключаем регистрацию успешного завершения фонового задания
УстановитьИспользованиеСобытияЖурналаРегистрации("_$Job$_.Succeed", ИспользованиеСобытия);
Важные нюансы реализации данного способа:
Наиболее надежным и профессиональным решением является изменение логики работы самого регламентного задания. Вместо того чтобы запускать фоновое задание каждые 5 секунд силами планировщика 1С, мы можем запускать его один раз (например, раз в день) и внутри процедуры организовать непрерывный цикл обработки данных с паузами.
Для реализации безопасной задержки выполнения (паузы) на стороне сервера без создания избыточной нагрузки на процессор можно использовать метод ожидания завершения вспомогательного фонового задания. Рассмотрим пример реализации процедуры паузы:
Процедура Пауза(Секунд) Экспорт
ТекущийСеансИнформационнойБазы = ПолучитьТекущийСеансИнформационнойБазы();
ФоновоеЗадание = ТекущийСеансИнформационнойБазы.ПолучитьФоновоеЗадание();
Если ФоновоеЗадание = Неопределено Тогда
Параметры = Новый Массив;
Параметры.Добавить(Секунд);
// "ОбщегоНазначенияБТС" можно заменить на любой подходящий общий модуль
ФоновоеЗадание = ФоновыеЗадания.Выполнить("ОбщегоНазначенияБТС.Пауза", Параметры);
КонецЕсли;
Попытка
ФоновоеЗадание.ОжидатьЗавершения(Секунд);
Исключение
Возврат;
КонецПопытки;
КонецПроцедуры
В качестве более простой альтернативы для серверного кода, не требующей создания дочерних фоновых заданий, можно использовать вызов системной утилиты операционной системы через командную строку. Например, отправка команды ping на локальный адрес, которая приостановит выполнение потока на заданное количество секунд:
Процедура СистемнаяПауза(Секунд) Экспорт
КомандаЗапуска = "ping -n " + Формат(Секунд + 1, "ЧГ=0") + " 127.0.0.1";
ЗапуститьПриложение(КомандаЗапуска, , Истина);
КонецПроцедуры
Организация классического бесконечного цикла Пока Истина Цикл ... КонецЦикла в среде 1С несет в себе серьезные риски. При работе с HTTP-соединениями, чтении JSON, XML или использовании COM-объектов операционная система и рабочий процесс сервера 1С (rphost) могут накапливать утечки оперативной памяти. За несколько дней непрерывной работы «вечного» фонового задания процесс сервера может аварийно завершиться из-за нехватки ресурсов.
Чтобы избежать утечек памяти и зависаний, рекомендуется использовать концепцию «полувечного» цикла. При такой схеме регламентное задание работает в цикле с паузами фиксированное время (например, 10–15 минут), после чего корректно завершается. Платформа полностью освобождает занятую им оперативную память, а планировщик 1С запускает задание заново.
Разберем пример реализации схемы «полувечного» цикла:
Процедура ВыполнитьОбменДаннымиВЦикле() Экспорт
ВремяНачала = ТекущаяДата();
// Ограничиваем время жизни одного сеанса задания 15 минутами (900 секунд)
МаксимальноеВремяРаботы = 900;
Пока Истина Цикл
// Проверяем лимит времени работы для предотвращения утечек памяти
Если ТекущаяДата() - ВремяНачала > МаксимальноеВремяРаботы Тогда
Прервать; // Выходим из цикла, завершаем фоновое задание
КонецЕсли;
Попытка
// Выполняем порцию обмена с интернет-магазином
ВыполнитьПорциюОбмена();
Исключение
// Записываем только критические ошибки в Журнал Регистрации
ЗаписатьВЖурналРегистрации(
"ОбменИнтернетМагазин.Ошибка",
УровеньЖурналаРегистрации.Ошибка,
,
,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке())
);
КонецПопытки;
// Делаем паузу перед следующей итерацией обмена
Пауза(5);
КонецЦикла;
КонецПроцедуры
При таком подходе количество системных записей в ЖР сократится с 34 000 до всего 96 записей в сутки, что полностью решит проблему избыточной нагрузки на Журнал регистрации.
Начиная с платформы 8.3.5, журнал регистрации по умолчанию хранится в новом формате — СУБД SQLite (файлы с расширением .lgd). При частой записи событий (каждые 5 секунд) эта база данных начинает испытывать серьезные проблемы с блокировками (ошибки вида Database Locked).
Поскольку SQLite не рассчитана на высокую интенсивность одновременных транзакций записи, постоянные попытки фоновых заданий зарегистрировать свой старт могут парализовать запись любых других логов в системе. Кроме того, физический файл базы данных SQLite не уменьшается в размерах при удалении старых записей из ЖР без выполнения монопольной операции сжатия (команда VACUUM). Переход на схему циклического выполнения с паузами полностью нивелирует эти риски. Для безопасного чтения данных без риска взаимоблокировок базы можно использовать утилиту для поиска событий в 1Cv8.lgd без блокировки работы пользователей.
При переходе на использование длинных циклов обмена возникает риск того, что регламентное задание может аварийно завершиться или зависнуть, остановив весь процесс обмена. Чтобы этого не произошло, мы рекомендуем настроить второе регламентное задание-наблюдатель (Watchdog). Оно должно запускаться раз в 10 минут и проверять, активно ли основное фоновое задание обмена. Для автоматического отслеживания подобных сбоев можно использовать обработку для анализа журнала регистрации и оповещения об ошибках регламентных заданий.
Проанализируем пример кода для проверки активности основного задания:
Процедура КонтрольРаботоспособностиОбмена() Экспорт
Отбор = Новый Структура;
Отбор.Вставить("ИмяРегламентногоЗадания", "РегламентноеЗаданиеОбменИнтернетМагазин");
Отбор.Вставить("Состояние", СостояниеФоновогоЗадания.Активно);
АктивныеЗадания = ФоновыеЗадания.ПолучитьФоновыеЗадания(Отбор);
Если АктивныеЗадания.Количество() = 0 Тогда
// Задание не запущено или упало. Записываем предупреждение и перезапускаем
ЗаписатьВЖурналРегистрации(
"ОбменИнтернетМагазин.Внимание",
УровеньЖурналаРегистрации.Предупреждение,
,
,
"Обнаружена остановка фонового задания обмена. Производится перезапуск."
);
// Вызываем принудительный запуск регламентного задания
ВыполнитьРегламентноеЗаданиеОбмена();
КонецЕсли;
КонецПроцедуры
Для предотвращения раздувания журнала регистрации и оптимизации производительности СУБД при частых обменах:
УстановитьИспользованиеСобытияЖурналаРегистрации() только в крайних случаях, когда внесение изменений в архитектуру кода конфигурации невозможно.