Почему HTTP-сервис 1С на веб-сервере IIS не возвращает ответ при передаче больших данных

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

Разработка HTTP-сервисов на платформе 1С:Предприятие 8.3 — это удобный и современный способ интеграции различных систем. Однако при росте объемов передаваемых данных разработчики часто сталкиваются с крайне неприятной проблемой: при попытке передать файл или JSON-пакет размером более 15–20 Мегабайт клиент не получает вообще никакого ответа (возникает ошибка типа "пустой ответ", "соединение разорвано" или "Connection Reset"). При этом, если анализировать код на стороне 1С, все процедуры выполняются корректно вплоть до финальной строки возврата ответа.

В этой статье мы подробно разберем, почему возникает данная проблема, как диагностировать ее истинную причину на уровне операционной системы и веб-сервера IIS, а также детально рассмотрим пошаговые решения как на стороне настройки сервера, так и на уровне оптимизации кода 1С.

В чем кроется истинная причина проблемы?

Когда HTTP-сервис 1С отрабатывает до конца, формируя итоговый объект HTTPСервисОтвет, но клиент получает пустой ответ (0 байт), это означает, что веб-сервер IIS (Internet Information Services) разорвал сетевое соединение в процессе передачи данных или непосредственно перед ней. Выделим три основные причины, почему это происходит:

  1. Аварийное завершение процесса IIS (Crash процесса w3wp.exe). При формировании огромного текстового ответа в оперативной памяти 1С создает гигантские строки. Если пул приложений IIS работает в 32-битом режиме, ему доступно не более 2 ГБ адресного пространства. При фрагментации памяти процесс выделения единого непрерывного блока под строку размером 20–40 МБ вызывает критическую ошибку Out Of Memory (или Access Violation 0xc0000005), из-за чего рабочий процесс IIS мгновенно падает.
  2. Тайм-ауты обработки запроса. Сборка больших массивов информации в JSON и их последующая сериализация — ресурсоемкие операции. Если время формирования и передачи превышает лимиты ожидания веб-сервера или сетевых шлюзов, соединение принудительно закрывается.
  3. Ограничения веб-сервера на размер ответа и буферизацию. Функции динамического сжатия контента на IIS или некорректно настроенные фильтры запросов могут блокировать передачу пакетов, превышающих стандартные лимиты.

Давайте пошагово разберем, как исправить каждую из этих проблем.

Шаг 1. Диагностика падения процесса w3wp.exe в операционной системе

Прежде чем менять настройки программного кода, нам необходимо убедиться, что проблема действительно вызвана аварийным завершением процесса веб-сервера IIS. Для этого выполним следующие действия:

  1. Откроем стандартную утилиту Windows Просмотр событий (Event Viewer) на сервере, где опубликован веб-сервис.
  2. Перейдем в ветку Журналы Windows -> Приложение (Application).
  3. Выполним поиск событий с уровнем Ошибка (Error) и источником Application Error или IIS-W3SVC-WP.
  4. Если в момент отправки запроса мы видим ошибку падения процесса w3wp.exe с кодом исключения 0xc0000005 и указанием на библиотеки backend.dll или backbas.dll, значит, рабочему процессу веб-сервера не хватает оперативной памяти для обработки сформированной строки.

Для устранения этой проблемы переведем пул приложений IIS исключительно в 64-разрядный режим:

  1. Запустим Диспетчер служб IIS.
  2. В левом дереве выберем пункт Пулы приложений (Application Pools).
  3. Найдем пул, под которым работает наша опубликованная база 1С, нажмем по нему правой кнопкой мыши и выберем Дополнительные параметры (Advanced Settings).
  4. Найдем параметр Разрешены 32-разрядные приложения (Enable 32-Bit Applications) и установим его значение в False.
  5. Убедимся, что на самом сервере установлена 64-битная версия платформы 1С:Предприятие и соответствующий ей 64-разрядный модуль расширения веб-сервера.

Шаг 2. Оптимизация кода 1С: Уход от формирования строк в ОЗУ

Первоначальный вариант кода автора темы страдает серьезным недостатком с точки зрения потребления оперативной памяти:


СтрокаJSON = ПолучитьСтрокуJSON(СтруктураВыгрузки);    
Ответ = СтрокаJSON;
HTTPОтвет = Новый HTTPСервисОтвет(200);
HTTPОтвет.УстановитьТелоИзСтроки(Ответ);

Метод ПолучитьСтрокуJSON() пытается целиком уместить весь объем выгрузки в одну переменную типа "Строка". При объемах данных более 15–30 МБ это приводит к выделению огромных объемов памяти (в несколько раз превышающих размер самого JSON из-за особенностей внутреннего представления строк UTF-16 в платформе 1С). Метод УстановитьТелоИзСтроки() выполняет повторное копирование и перекодирование данных в UTF-8, что удваивает пиковое потребление памяти.

Для радикального снижения нагрузки на ОЗУ мы должны использовать потоковую запись данных во временный файл на диске, а затем отдавать этот файл напрямую клиенту через метод УстановитьТелоИзФайла(). Рассмотрим правильный шаблон реализации HTTP-сервиса:


// Создаем временный файл для записи JSON
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("json");

// Настраиваем потоковую запись данных на диск
ЗаписьJSON = Новый ЗаписьJSON;
ПараметрыЗаписиJSON = Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Нет, " ", Истина);
ЗаписьJSON.ОткрытьФайл(ИмяВременногоФайла, КодировкаТекста.UTF8,,, ПараметрыЗаписиJSON);

// Выполняем сериализацию непосредственно в файл, минуя оперативную память
ЗаписатьJSON(ЗаписьJSON, СтруктураВыгрузки);
ЗаписьJSON.Закрыть();

// Формируем HTTP-ответ
HTTPОтвет = Новый HTTPСервисОтвет(200);
// Платформа 1С и IIS отправят файл клиенту в виде потока напрямую с диска
HTTPОтвет.УстановитьТелоИзФайла(ИмяВременногоФайла);
HTTPОтвет.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");

Возврат HTTPОтвет;

При таком подходе потребление оперативной памяти процессом w3wp.exe снижается в десятки раз. Даже выгрузки объемом в сотни мегабайт будут выполняться стабильно и быстро без риска переполнения ОЗУ.

Шаг 3. Настройка ограничений веб-сервера IIS и тайм-аутов

Если после перевода пула приложений в 64-разрядный режим и оптимизации кода проблема сохраняется, нам необходимо скорректировать настройки веб-сервера IIS, отвечающие за тайм-ауты и ограничения размеров передаваемого контента.

Проанализируем конфигурационный файл web.config, который находится в каталоге публикации нашей базы 1С. Нам необходимо убедиться, что лимиты времени ожидания и размеры файлов установлены с запасом. Добавим или изменим следующие параметры в секции <system.web> и <system.webServer>:


<configuration>
  <system.web>
    <!-- Увеличиваем время ожидания выполнения запроса (executionTimeout в секундах, например 3600 = 1 час) 
         и максимальный размер запроса (maxRequestLength в Килобайтах, например 204800 = 200 МБ) -->
    <httpRuntime executionTimeout="3600" maxRequestLength="204800" />
  </system.web>
  <system.webServer>
    <security>
      <requestFiltering>
        <requestLimits maxAllowedContentLength="209715200" /> <!-- Максимальный размер контента в Байтах (например, 200 МБ) -->
      </requestFiltering>
    </security>
  </system.webServer>
</configuration>

Также важно обратить внимание на настройки **Тайм-аута подключения (Connection Timeout)** в самом веб-интерфейсе IIS:

  1. В диспетчере IIS выберите ваш сайт (например, "Default Web Site").
  2. В панели Действия (Actions) справа нажмите Пределы (Limits...).
  3. Увеличьте параметр Тайм-аут подключения (в секундах) (Connection timeout). По умолчанию там установлено значение 120 секунд. При передаче очень больших файлов по медленным каналам связи этого времени может не хватить, и сервер закроет соединение до завершения передачи.

Шаг 4. Отключение динамического сжатия ответов

По умолчанию в IIS может быть включена функция **Динамического сжатия содержимого (Dynamic Content Compression)**. Для небольших JSON-ответов это полезно, так как экономит трафик. Но при передаче динамически генерируемых JSON-пакетов объемом более 15 МБ IIS начинает буферизировать весь ответ в памяти для сжатия "на лету". Это может приводить к огромным задержкам, росту потребления памяти и аварийному сбросу соединения.

Попробуем отключить динамическое сжатие для нашей публикации 1С:

  1. В диспетчере IIS выберите вашу публикацию (веб-приложение 1С).
  2. В центральной панели найдите и откройте раздел Сжатие (Compression).
  3. Снимите флажок Включить сжатие динамического содержимого (Enable dynamic content compression).
  4. Примените изменения и перезапустите IIS командой iisreset в командной строке от имени администратора.

Шаг 5. Постраничная выгрузка данных (Пагинация) как альтернатива

Передача сверхбольших объемов данных одним непрерывным HTTP-запросом считается плохой практикой интеграции. Если объем данных растет и начинает превышать разумные пределы, мы рекомендуем спроектировать архитектуру обмена с использованием **пагинации (постраничной выгрузки)**.

Рассмотрим, как можно доработать логику запроса. Клиент при вызове HTTP-сервиса должен передавать параметры пагинации, например РазмерСтраницы (сколько элементов вернуть за один раз) и НомерСтраницы (или смещение ПропуститьЭлементов). Пример обработки параметров в 1С:


ПараметрыЗапроса = URLПараметры(Запрос); // Пользовательская функция разбора GET-параметров
РазмерСтраницы = ПараметрыЗапроса.Получить("Limit");
НомерСтраницы = ПараметрыЗапроса.Получить("Page");

Если РазмерСтраницы = Неопределено Тогда
    РазмерСтраницы = 1000; // По умолчанию отдаем порциями по 1000 элементов
КонецЕсли;

// Формируем запрос к базе данных с использованием конструкции ВЫБРАТЬ ПЕРВЫЕ...
ЗапросБД = Новый Запрос;
ЗапросБД.Текст = 
    "ВЫБРАТЬ ПЕРВЫЕ " + Формат(РазмерСтраницы, "ЧГ=0") + "
    |    Номенклатура.Ссылка КАК Ссылка,
    |    Номенклатура.Наименование КАК Наименование
    |ИЗ
    |    Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |    Номенклатура.Код > &ПоследнийКод
    |УПОРЯДОЧИТЬ ПО
    |    Номенклатура.Код";

// Передаем параметры пагинации и выполняем выгрузку порциями

Использование пагинации позволяет гарантировать, что объем одного HTTP-ответа никогда не превысит безопасный лимит (например, 2-3 Мегабайта), а общая скорость получения всего массива данных может даже увеличиться за счет параллельной обработки мелких пакетов.

Выводы и чек-лист устранения проблемы

Если ваш HTTP-сервис 1С "молча" прекращает работу при больших запросах, выполните следующие действия:

← На главную