Почему тормозит подключение к веб-сервису и возникают задержки в 10 секунд при создании WSОпределения?

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

При интеграции 1С с внешними системами через SOAP (веб-сервисы) разработчики часто сталкиваются с "мистическими" проблемами производительности. Одна из самых распространенных ситуаций: выполнение кода подключения на сервере иногда происходит мгновенно, а иногда зависает ровно на 10 или 20 секунд. Когда проводится замер производительности контура 1С и поиск узких мест, выясняется, что задержки возникают в самых неожиданных точках. Давайте подробно разберем, почему это происходит, как диагностировать проблему и, самое главное, как её правильно решить, опираясь на опыт сообщества и технические особенности протоколов.

Суть проблемы

Рассмотрим типичный код, который вызывает вопросы. Мы пытаемся создать определение веб-сервиса, обращаясь к WSDL-описанию на удаленном сервере:


// Пример проблемного кода
ОпределениеТ = Новый WSОпределения("http://serverB:9997/Exchange/?singleWsdl", , , , Таймаут);

Симптомы следующие:

  1. Код выполняется на сервере 1С (Сервер А).
  2. Целевой сервис (Сервер Б) может быть написан не на 1С (например, .NET/WCF, Java).
  3. Периодически возникает пауза ровно в 10 или 20 секунд перед продолжением выполнения.
  4. Ошибок при этом может не возникать, соединение в итоге устанавливается.

Если вы столкнулись с задержкой, кратной 10 секундам, это практически всегда указывает на таймаут сетевого протокола или ожидания ответа от зависимого ресурса. Давайте проанализируем основные причины и способы решения.

Причина 1: Проблемы с DNS и конфликты IPv6/IPv4

Одной из самых частых причин "плавающих" задержек является некорректная настройка разрешения имен (DNS) в операционной системе Windows Server.

Механизм возникновения:

Современные ОС по умолчанию пытаются использовать протокол IPv6. Когда платформа 1С обращается к адресу serverB, операционная система сначала пытается разрешить это имя в IPv6-адрес. Если сеть не настроена для IPv6, система ждет ответа от DNS-сервера до истечения таймаута (часто это именно 10 секунд), и только не получив ответа, переключается на IPv4, который срабатывает мгновенно.

Почему проблема плавающая?

После успешного разрешения имени результат кэшируется. Пока запись в кэше DNS жива, запросы проходят мгновенно. Как только кэш очищается — снова возникает 10-секундная пауза. Чтобы точно понимать, под каким адресом сервер обращается к внешним ресурсам, можно использовать MyIP сервис на скрипте Python, который поможет в диагностике сетевых идентификаторов.

Решение:

Чтобы исключить влияние DNS и NetBIOS-запросов, мы рекомендуем прописать жесткое соответствие IP-адреса и имени хоста в файле hosts на сервере, где работает 1С.

  1. Откройте файл C:\Windows\System32\drivers\etc\hosts от имени администратора.
  2. Добавьте строку: 192.168.1.XX serverB (укажите реальный IP и имя).

Причина 2: Внешние схемы XSD в WSDL-файле

Это более тонкая проблема, связанная с тем, как платформа 1С парсит полученный WSDL. Если в тексте WSDL содержатся ссылки на внешние пространства имен (namespaces), платформа попытается их скачать для валидации схемы.

Как это работает:

В WSDL часто встречаются теги import или include, ссылающиеся на схемы, расположенные на сайтах w3.org, microsoft.com или других ресурсах. Если у сервера 1С нет прямого доступа в интернет (или он ограничен строгим фаерволом), платформа пытается установить соединение с этими адресами.

Происходит следующее:

  1. 1С скачивает основной WSDL.
  2. Видит ссылку на внешний XSD.
  3. Пытается скачать XSD.
  4. Фаервол молча отбрасывает пакеты (DROP) или интернет недоступен.
  5. Платформа ждет стандартный TCP-таймаут (обычно около 20 секунд).
  6. По истечении времени платформа либо выдает ошибку, либо игнорирует схему и продолжает работу (если валидация не строгая).

Решение: Использование статических WSDL (см. раздел "Правильная архитектура" ниже).

Причина 3: Особенности WCF и параметр ?singleWsdl

В приведенном примере используется параметр ?singleWsdl. Это характерно для сервисов на базе Microsoft WCF (.NET). Стандартный запрос ?wsdl часто возвращает "облегченную" структуру, где схемы разнесены по разным файлам. Запрос singleWsdl заставляет сервер собрать все метаданные в один большой XML-файл.

Если на стороне Сервера Б приложение "засыпает" (IIS App Pool Recycling) из-за простоя, то первый запрос будет долгим, так как серверу нужно:

  1. Запустить рабочий процесс.
  2. Сгенерировать единую схему WSDL.

Это может давать задержку, но она обычно связана с генерацией ответа, а не сетевым таймаутом.

Методы диагностики

Прежде чем применять "лекарства", нужно точно поставить диагноз. Рассмотрим, как это сделать.

1. Сетевой дамп (Wireshark)

Это самый надежный способ. Запустите сниффер на сервере 1С и отфильтруйте трафик по IP-адресу веб-сервиса. Посмотрите на временные метки:

2. Нагрузочное тестирование фоновыми заданиями

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

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


Процедура ЗапуститьНагрузочныйТест()
    
    МассивЗаданий = Новый Массив;
    ПараметрыЗадания = Новый Массив;
    
    // Запускаем 10 параллельных потоков
    Для Сч = 1 По 10 Цикл
        Задание = ФоновыеЗадания.Выполнить("МойМодуль.ПроверитьПодключениеКСервису", ПараметрыЗадания);
        МассивЗаданий.Добавить(Задание);
    КонецЦикла;
    
    // Ожидаем завершения
    ФоновыеЗадания.ОжидатьЗавершения(МассивЗаданий);
    
    // Здесь можно проанализировать журнал регистрации, 
    // куда фоновые задания должны писать время выполнения
    
КонецПроцедуры

Правильная архитектура решения

В ходе обсуждения предлагалось использовать глобальную переменную для хранения соединения. Это рабочий вариант ("Костыль"), но он имеет недостатки: соединение может разорваться, и его придется пересоздавать.

Использование статического WSDL-файла (Best Practice)

Самое надежное решение, которое устраняет 90% проблем с задержками при инициализации — это отказ от получения WSDL по сети в момент работы.

Как это сделать:

  1. Скачайте WSDL-файл с адреса http://serverB:9997/Exchange/?singleWsdl с помощью браузера и сохраните его как XML файл.
  2. Если в файле есть ссылки на внешние XSD (теги import), скачайте их тоже и положите рядом.
  3. Отредактируйте WSDL файл: замените все ссылки http://... в тегах schemaLocation на относительные пути к локальным файлам.
  4. Добавьте этот файл (и XSD схемы) в макеты конфигурации (как ДвоичныеДанные или ТекстовыйДокумент) или просто сохраните в папку на сервере 1С.

Теперь инициализируйте веб-сервис из локального файла:


// Создаем WS-определения мгновенно из файла, без сетевых запросов
// ПутьКФайлу - это локальный путь к wsdl на диске сервера
ОпределениеТ = Новый WSОпределения(ПутьКФайлу);

// Создаем прокси
Прокси = Новый WSПрокси(ОпределениеТ, URIПространстваИмен, ИмяСервиса, ИмяТочкиПодключения);

// Важно: явно указываем адрес реального сервиса, 
// так как в локальном файле может быть старый адрес или localhost
Прокси.ТочкаПодключения.Адрес = "http://serverB:9997/Exchange/";

// Вызываем метод
Результат = Прокси.МойМетод();

Преимущества такого подхода:

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

Итоги

Если у вас "тормозит" веб-сервис при подключении:

  1. Проверьте файл hosts на наличие привязки IP к имени.
  2. Убедитесь, что WSDL не тянет за собой схемы из недоступного интернета.
  3. Не используйте динамическое получение WSDL в высоконагруженных местах. Перейдите на инициализацию из локального файла (макета).
← На главную