Почему зависает отправка HTTP-запроса из 1С и как решить проблему блокировки базы

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия IT и автоматизация бизнеса
← На главную

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

Причины бесконечного ожидания ответа и блокировки файловой базы

Проанализируем механику возникновения ошибки. Когда программа выполняет сетевой вызов (например, через метод ОтправитьДляОбработки или ВызватьHTTPМетод), платформа открывает сетевой сокет и ожидает ответа от удаленного сервера.

Выделим ключевые факторы, приводящие к зависанию:

  1. Перехват трафика веб-экраном антивируса: модули веб-защиты и проверки SSL-трафика работают как локальные прозрачные прокси-серверы. Если защитный экран не может проверить или корректно пропустить поток данных, он может заморозить сетевой сокет без отправки пакетов разрыва соединения (TCP RST/FIN). В результате клиент 1С остается в бесконечном ожидании.
  2. Таймаут по умолчанию равен 0: если в конструкторе HTTPСоединение не задан параметр таймаута, платформа ожидает ответ бесконечно. Поскольку сетевой разрыв не происходит, код не переходит в ветку Исключение.
  3. Индивидуальные настройки пользователей: разное поведение под разными пользователями базы в рамках одной операционной системы часто обусловлено тем, что в типовых конфигурациях (на базе БСП) персональные сетевые настройки и параметры прокси-сервера сохраняются индивидуально. В зависимости от них трафик может направляться напрямую либо через системный стек, попадая под фильтры безопасности.
  4. Блокировка таблиц базы данных: если отправка HTTP-запроса выполняется внутри транзакции (явной через НачатьТранзакцию() или неявной в обработчиках событий объекта ПередЗаписью, ПриЗаписи), в файловом режиме блокируется файл *.1CD. Пока первый пользователь ожидает завершения запроса, работа остальных сеансов полностью парализуется.

Шаг 1. Настройка сетевой защиты и исключений антивируса

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

  1. Добавим исполняемые файлы платформы 1cv8.exe и 1cv8c.exe в список доверенных программ антивируса и брандмауэра.
  2. В настройках веб-экрана антивируса отключим проверку HTTPS/SSL для доверенного адреса веб-сервера, на который выполняется отправка файлов.
  3. Добавим целевой домен и порт сервиса в список исключений сетевого сканирования.

Шаг 2. Корректное указание таймаута в конструкторе HTTPСоединение

Посмотрим на частую ошибку: свойство Таймаут у объекта HTTPСоединение доступно только для чтения, поэтому попытка установить его напрямую (например, Соединение.Таймаут = 10;) вызовет исключение «Поле объекта недоступно для записи».

Таймаут задается строго через конструктор объекта. Разберем синтаксис конструктора платформы:

Новый HTTPСоединение(<Сервер>, <Порт>, <Пользователь>, <Пароль>, <Прокси>, <Таймаут>, <ЗащищенноеСоединение>, <ИспользоватьАутентификациюОС>)

Обратите внимание на строгую позиционность параметров. Параметр Таймаут идет шестым по счету. Если прокси-сервер не используется, на его место обязательно нужно передать Неопределено, иначе числовое значение таймаута попадет в параметр прокси и соединение завершится с ошибкой.

Рассмотрим правильный пример инициализации защищенного соединения с явным ограничением времени ожидания в 30 секунд:


Сервер = "api.mysite.ru";
Порт = 443;
Таймаут = 30; // Время ожидания в секундах

// Инициализируем защищенное SSL-соединение
Защита = Новый ЗащищенноеСоединениеOpenSSL();

Попытка
    Соединение = Новый HTTPСоединение(
        Сервер,
        Порт,
        , // Пользователь веб-сервиса (если не требуется — пропускаем)
        , // Пароль веб-сервиса
        Неопределено, // Прокси (обязательно Неопределено, чтобы не сбить позицию таймаута)
        Таймаут,
        Защита
    );
Исключение
    ЗаписьЖурналаРегистрации("HTTPОбмен", УровеньЖурналаРегистрации.Ошибка,,, 
        "Не удалось создать HTTPСоединение: " + ОписаниеОшибки());
    ВызватьИсключение;
КонецПопытки;

Шаг 3. Переход на современную объектную модель HTTP-запросов

Рассмотрим современный способ отправки файлов на сервер. Устаревший метод ОтправитьДляОбработки с передачей путей файлов напрямую имеет ряд ограничений по управлению заголовками. Рекомендуется использовать связку объектов HTTPЗапрос и HTTPОтвет.

Посмотрим на пример отправки файла методом POST с контролем результата:


АдресРесурса = "/api/v1/upload";
ПутьКФайлу = "C:\temp\upload_data.zip";

// Формируем HTTP-запрос
Запрос = Новый HTTPЗапрос(АдресРесурса);
Запрос.Заголовки.Вставить("Content-Type", "application/octet-stream");
Запрос.Заголовки.Вставить("Accept", "application/json");

// Устанавливаем файл в тело запроса
Запрос.УстановитьИмяФайлаТела(ПутьКФайлу);

Попытка
    // Отправляем запрос и получаем объект HTTPОтвет
    Ответ = Соединение.ОтправитьДляОбработки(Запрос);
    
    Если Ответ.КодСостояния = 200 ИЛИ Ответ.КодСостояния = 201 Тогда
        ТекстОтвета = Ответ.ПолучитьТелоКакСтроку();
        // Обработка успешного ответа сервера
    Иначе
        ЗаписьЖурналаРегистрации("HTTPОбмен", УровеньЖурналаРегистрации.Предупреждение,,,
            СтрШаблон("Сервер вернул код ошибки: %1. Ответ: %2", Ответ.КодСостояния, Ответ.ПолучитьТелоКакСтроку()));
    КонецЕсли;
Исключение
    // Сюда программа попадет, если сработает таймаут или оборвется сеть
    ЗаписьЖурналаРегистрации("HTTPОбмен", УровеньЖурналаРегистрации.Ошибка,,,
        "Ошибка при отправке данных: " + ОписаниеОшибки());
    ВызватьИсключение;
КонецПопытки;

Рекомендации по предотвращению взаимных блокировок

Чтобы отправка файлов не мешала работе других пользователей в файловой базе, придерживаемся следующих правил:

  1. Вынос сетевых вызовов за рамки транзакций: никогда не вызывайте внешние веб-сервисы внутри обработчиков проведения или записи объектов. Сначала выполните HTTP-запрос, получите и проверьте ответ сервера, и только после успешного завершения открывайте транзакцию для сохранения данных в базу.
  2. Использование фоновых заданий: для тяжелых выгрузок файлов используйте запуск через ФоновыеЗадания.Выполнить(). Это сохранит отзывчивость пользовательского интерфейса даже при длительной сетевой операции.
← На главную