В процессе эксплуатации информационных баз 1С:Предприятие 8.3 разработчики и администраторы нередко сталкиваются с ситуацией, когда регламентное задание, обычно выполняющееся за несколько десятков секунд, неожиданно зависает на неопределенный срок. При этом сеанс фонового задания продолжает висеть в консоли администрирования кластера серверов, блокирует последующие запуски по расписанию и снимается только после перезапуска службы кластера 1С. Разберем по шагам, почему возникает такое поведение, как локализовать место сбоя и какие системные настройки гарантируют стабильную работу обменов.
Если зависающее фоновое задание связано с обменом данными (выгрузка файлов каталогов, остатков, заказов или прайс-листов во внешние системы), в подавляющем большинстве случаев зависание происходит на уровне сетевого вызова встроенного объекта FTPСоединение при выполнении методов Записать() или Получить().
По умолчанию, если при инициализации объекта не передан таймаут, операционная система может удерживать открытый сетевой сокет часами, ожидая ответа от удаленного сервера. Если на промежуточном сетевом оборудовании (роутере, межсетевом экране, NAT-шлюзе) происходит тихий сброс сессии (silent drop) без отправки TCP-пакета с флагом RST, 1С продолжает бесконечно ожидать ответа. Решением проблемы является обязательное явное указание таймаута при создании объекта.
Рассмотрим пример корректной инициализации FTP-подключения с контролем времени ожидания и пассивным режимом:
ТаймаутПодключения = 30; // Таймаут в секундах
ПассивныйРежим = Истина;
ПортFTP = 21;
Попытка
СоединениеFTP = Новый FTPСоединение(
АдресСервера,
ПортFTP,
ПользовательFTP,
ПарольFTP,
, // Прокси
ПассивныйРежим,
ТаймаутПодключения
);
СоединениеFTP.Записать(ПутьКЛокальномуФайлу, ПутьНаСервере);
// Освобождаем дескрипторы для сборщика мусора
СоединениеFTP = Неопределено;
Исключение
СоединениеFTP = Неопределено;
ЗаписьЖурналаРегистрации(
"ВыгрузкаFTP",
УровеньЖурналаРегистрации.Ошибка,,,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке())
);
ВызватьИсключение;
КонецПопытки;
Обратите внимание на явное присвоение переменной значения Неопределено в блоке исключения и после успешной отправки. Это позволяет рабочему процессу rphost своевременно закрыть файловые и сетевые дескрипторы сокетов, предотвращая утечки ресурсов операционной системы.
Еще одной распространенной причиной зависания метода Записать() или Получить() является работа в активном режиме FTP. Выясним разницу:
FTPСоединение параметр ПассивныйРежим должен быть явно установлен в значение Истина.Проанализируем распространенную ситуацию: регламентное задание не зависает физически, но создает иллюзию непрерывного зависания. Это происходит, когда в свойствах расписания регламентного задания настроен бесконечный перезапуск при ошибке.
Если регламентное задание по-прежнему зависает, необходимо точно установить, на какой строке исходного кода останавливается выполнение. Разберем два основных инструмента локализации проблемы.
Способ 1. Точечное логирование в Журнал регистрации
Добавим в код регламентной процедуры контрольные точки перед каждым потенциально опасным действием:
ЗаписьЖурналаРегистрации("ФоновыйОбмен", УровеньЖурналаРегистрации.Информация,,, "Начало формирования файла выгрузки");
СформироватьФайлНаДиске(ПутьКФайлу);
ЗаписьЖурналаРегистрации("ФоновыйОбмен", УровеньЖурналаРегистрации.Информация,,, "Попытка подключения к FTP-серверу");
ПодключитьсяКFTP(ПараметрыПодключения);
ЗаписьЖурналаРегистрации("ФоновыйОбмен", УровеньЖурналаРегистрации.Информация,,, "Отправка файла по FTP начата");
ОтправитьФайл(ПутьКФайлу);
ЗаписьЖурналаРегистрации("ФоновыйОбмен", УровеньЖурналаРегистрации.Информация,,, "Выгрузка успешно завершена");
Сравнивая временные метки событий в журнале регистрации, можно точно определить шаг, после которого запись перестает появляться, что указывает на зависшую операцию.
Способ 2. Технологический журнал платформы
Для серверных баз (включая базы на СУБД PostgreSQL) эффективным методом является настройка технологического журнала (logcfg.xml) на сбор событий:
EXCP — фиксирует системные исключения и сетевые разрывы;TIMEOUT и TLOCK — отслеживают таймауты управляемых блокировок и взаимные блокировки данных в СУБД;SCALL — регистрирует длительные вызовы серверных процедур.Иногда зависание регламентного задания вызвано не сетевым протоколом, а блокировками транзакций. Перед отправкой файла задание часто считывает данные из таблиц регистрации изменений или записывает статус выгрузки в регистр сведений.
Если другое задание или действие пользователя параллельно блокирует те же строки, процесс уходит в ожидание. Для PostgreSQL рекомендуется настроить защитные лимиты в файле postgresql.conf:
lock_timeout — задает максимальное время ожидания захвата блокировки таблицы или строки. Если время превышено, СУБД прерывает команду, и платформа 1С получает управляемую ошибку, которую можно обработать в конструкции Попытка ... Исключение.statement_timeout — ограничивает максимальное время выполнения любого SQL-запроса, предотвращая бесконечное выполнение дефектных планов запросов.idle_in_transaction_session_timeout — автоматически закрывает соединения, которые открыли транзакцию и перешли в режим ожидания.Если встроенный механизм FTPСоединение продолжает работать нестабильно из-за особенностей локальной сетевой инфраструктуры или прокси-серверов, рассмотрим альтернативные варианты передачи данных:
curl) через метод ЗапуститьПриложение(). Данные утилиты позволяют тонко задавать параметры подключения, таймауты на соединение, максимальную скорость передачи и гарантированно завершают дочерний процесс операционной системы.HTTPСоединение либо использование безопасного протокола SFTP. Протокол HTTP работает через единый стандартный порт, прозрачно маршрутизируется прокси-серверами и не имеет проблем с блокировкой динамических портов брандмауэрами.