358 документов
← К списку

Таймауты при работе с внешними ресурсами

страница

#std748

Область применения: управляемое приложение, обычное приложение.

1. При работе с внешними ресурсами с помощью объектов WSОпределения, WSПрокси, HTTPСоединение, FTPСоединение, ИнтернетПочтовыйПрофиль следует задавать таймаут – предельное время  ожидания выполнения операции. В противном случае, в результате бесконечного ожидания программа зависнет или часть функционала программы станет недоступна.

Установка таймаута является защитой от целого ряда внешних факторов:

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

Например, при получении описания веб-сервиса и вызове его операций – если удаленная сторона долго не отвечает (например, выключена, находится на обслуживании или возникли временные неполадки), ожидание ответа может длиться бесконечно. Поэтому если веб-сервис был вызван в результате интерактивных действий пользователя, то внешне будет выглядеть так, что «программа зависла»; а если веб-сервис вызывается из регламентного задания, то связанная с ним часть функционала программы может стать недоступна.

2. В общем виде, время выполнения операции с внешними ресурсами складывается из шести этапов:

  • DNS Lookup — время, потраченное на определение IP адреса по доменному имени (если применимо);
  • Connect — установка соединения с веб-сервером по полученному IP-адресу;
  • Send — отправка данных на веб-сервер;
  • Wait — ждем, пока данные дойдут до веб-сервера и он их обработает;
  • Receive — получение ответа от веб-сервера;
  • Cache Read – получение данных от веб-сервера.

Например, при таймауте в 60 секунд программа и вызываемый внешний ресурс должны успеть выполнить шесть выше перечисленных этапов операции, иначе соединение будет разорвано, а передача данных прервана. Однако если в процессе выполнения операции возникнет сбой, то система и/или пользователь будет зря ожидать 60 секунд.

Поэтому величину таймаута рекомендуется определять, исходя из ожидаемого времени выполнения конкретной операции:

  • Для быстрых операций (например, проверка доступности сервера) величина таймаута должна выбираться, соответственно, небольшой;
  • В общем случае, не следует выбирать таймаут более 3 минут, чтобы при недоступности удаленной стороны не допустить эффект «зависания» программы;
  • Но если операция выполняется долго из-за этапов Send или Cache Read, т.е. это передача больших объемов данных на веб-сервер или загрузка большого файла с внешнего ресурса, то следует устанавливать большой таймаут, исходя из оценки объема передаваемых данных, но не более 12 часов.

Подобнее о рекомендуемых величинах таймаута для различных операций см. в таблице п. 4.

3. Рекомендации по снижению величин таймаута и повышению отзывчивости программы при работе с внешними ресурсами.

3.1. При разработке веб-сервисов, на операции которых предусмотрен таймаут более 20 секунд (ориентировочно), рекомендуется:

  • предусмотреть в веб-сервисе отдельную контрольную операцию Ping;
  • при работе с этим веб-сервисом, предварительно получать для нее прокси с небольшим таймаутом в 7 секунд и вызывать контрольную операцию Ping;
  • только после этого получать основной прокси.

Пример вызова веб-сервиса.

Неправильно

Правильно

Реализация модуля веб-сервиса PingPong:

Функция Pong(Знач Параметр)
  Возврат СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Привет, %1'"), Параметр);
КонецФункции

Функция Ping()
  Возврат Истина; // Проверка связи
КонецФункции

Функция Pong(Знач Параметр)
  Возврат СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Привет, %1'"), Параметр);
КонецФункции

Реализация вызывающей стороны (без использования Библиотеки стандартных подсистем):

// Ждем не более минуты
PingPong = Новый WSПрокси(АдресВебСервиса, , , , , 60);
Результат = PingPong.Pong(НСтр("ru = 'Мяч'"));

// Ждем не более 3 секунд
PingPong = Новый WSПрокси(АдресВебСервиса, , , , , 3);
PingPong.Ping(); // проверка связи

// Сервис жив, далее работаем с ним и ждем не более минуты
PingPong = Новый WSПрокси(АдресВебСервиса, , , , , 60); 
Результат = PingPong.Pong(НСтр("ru = 'Мяч'"));

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

  • для работы с веб-сервисами предназначена функция WSПрокси общего модуля ОбщегоНазначения (включает в себя поддержку контрольной операции Ping);
  • для получения данных по протоколам HTTP(S) и FTP(S) – подсистема «Получение файлов через Интернет».

Пример реализации вызывающей стороны с использованием Библиотеки стандартных подсистем:

// Сделать контрольный вызов Ping и ждать не более минуты на дальнейших операциях.
PingPong = ОбщегоНазначения.WSПрокси(АдресВебСервиса,..., 60, Истина);
// Сервис точно жив, далее работаем с ним.
Результат = PingPong.Pong(НСтр("ru = 'Мяч'"));

3.2. Для других видов внешних ресурсов (не веб-сервисов) рекомендуется применять аналоги операции Ping. Например:

  • для сервисов, работающих через REST API – это контрольная отправка тестовой команды; в большинстве случаев, если ответ с кодом 200, то сервис работает;
  • для FTP/WebDAV-ресурсов – это контрольная загрузка (отправка) файла-пустышки.

3.3. Веб-сервисы, операции, которых занимают объективно много времени из-за этапа Wait (т.е. долго отрабатывает само веб-приложение), и они не могут быть ускорены (оптимизированы) по объективным причинам, следует переводить на асинхронный режим выполнения:

  • запускать фоновое задание для выполнения подобной «тяжелой» операции,
  • и предусмотреть дополнительные операции по проверке готовности и получению результата.

Пример асинхронного вызова веб-сервиса.

Неправильно

Правильно

Реализация модуля веб-сервиса Long:

Функция GetData()
    Результат = <очень длительные вычисления>;
    Возврат Результат;
КонецФункции

Функция StartDoLong()
    // запуск фонового задания
    ИдентификаторОперации = ...
    // возвращаем идентификатор операции для отслеживания ее готовности
    Возврат ИдентификаторОперации;
КонецФункции

Функция IsReady(Знач ИдентификаторОперации)
    // проверяем, завершено ли фоновое задание по переданному идентификатору
    Готовность = ...
    Возврат Готовность;
КонецФункции

Функция GetData(Знач ИдентификаторОперации)
    Результат = <получаем уже готовый результат по переданному идентификатору >;
    Возврат Результат;
КонецФункции

Реализация вызывающей стороны:

Long = Новый WSПрокси(АдресВебСервиса, , , , , 600); // ждем 10 мин

Результат = Long.GetData();

Long = Новый WSПрокси(АдресВебСервиса, , , , , 600); // ждем 10 мин

ИдентификаторОперации = Long.StartDoLong();

Пока Не Long.IsReady(ИдентификаторОперации) Цикл
    <ждем определенный интервал времени>
КонецЦикла;
Результат = Long.GetData(ИдентификаторОперации);

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

4. Рекомендуемые величины таймаутов для различных операций:

Операция 

Таймаут (секунд)

Получение описания веб-сервиса 

7

Проверка корректности введенного адреса, взаимодействие с менеджером сервиса в модели сервиса и прочие «быстрые» операции

10-20

Получение сведений об одном контрагенте, обмен сообщениями, отправка SMS, удаленное администрирование ИБ в модели сервиса

60-1201

Передача сообщений обмена данными через веб-сервис или получение файлов из внешнего ресурса до 1 Мб.

120-1801

Загрузка файлов более 1 Мб

Если известен размер файла, то размер в мегабайтах * 1282, иначе предельное время загрузки, но не более 43200 3


1 Следует вызывать только после контрольной операции Ping.

2 Загрузка 1 мегабайта данных занимает 128 секунд, при скорости 64 кбит/с, т.к. сотовые операторы в определенных случаях ограничивают скорость загрузки этой величиной.

3 Таймаут продолжительностью 43200(12 часов) сек. является компромиссным решением, т.к. в случае нештатной ситуации процесс «отвиснет» на следующее утро и вернет управление, в отличие от полностью зависнувшей программы при неустановленном таймауте.