Параллельные HTTP-запросы

04.04.17

Разработка - Запросы

Демонстрируется пример параллельных http-запросов с использованием Msxml2.ServerXMLHTTP, WinHttp.WinHttpRequest, что позволяет получать данные сразу с множества ресурсов, экономя время, а также работать файловом режиме.

Когда необходимо производить обработку множетсва интернет-ресурсов (сайтов, web-сервисов и т.д.) , то остро встает проблема с производительностью приложения, так как при синхронных запросах время работы линейно зависит от количества запросов. Общее затраченное время  на получение ресурса можно сократить если использовать параллельную обработку ресурсов.

Один из вариантов решения задачи - это использование под Windows com-объекта Msxml2.ServerXMLHTTP, он позволяет производить асинхронное получение данных после запроса ресурса. Данный объект после получения данных может вызывать callback-фукнцию однако на чистом 1С мне не удалось ее запусить, но данный com-объект позволяет с помощью метода waitForResponse приостанавливать выполнение асинхронной операции ожидая завершения операции, вот этим и воспользуемся организовав тем самым подобие polling (частые опросы). Однако о чистой асинхронности говорить не приходится, так как работа пользователя будет заблокированна на время обработки ресурсов.

Рассмотрим на основе Msxml2.ServerXMLHTTP  пример опроса 30-и страниц статей с сайта microsoft.com, начиная со статьи про Msxml2.ServerXMLHTTP. Все дальнейшие рассуждения верны и для WinHttp.WinHttpRequest.

Подготовка:

Объекты = Новый Массив;
КоличествоОбъектов = 30;

Для ин = 0 По КоличествоОбъектов-1 Цикл
	ОбъектHTTP = Новый COMОбъект("Msxml2.ServerXMLHTTP.6.0");
	// таймаут 30 сек по всем операциям
	ОбъектHTTP.setTimeouts(30000,30000,30000,30000);
	// третий параметр указывает на асинхронность вызова
	ОбъектHTTP.open("GET", "https://msdn.microsoft.com/ru-ru/library/ms" + Формат(762278 + ин, "ЧГ=") + "(v=vs.85).aspx", Истина);		
	// отправляем запрос
	ОбъектHTTP.send();

	// сохраняем данные
	Данные = Новый Структура("Объект, Выполнено, Ошибка", ОбъектHTTP, Ложь, Ложь);
	Объекты.Добавить(Данные);			
КонецЦикла;

Далее запускаем цикл опроса созданных объектов, время ожидания для метода waitForResponse выбрано произвольным образом, очевидно, что оно не должно быть большим, иначе потеряем всю выгоду:

Пока Истина Цикл	
	ОбработаноОбъектов = 0;
	Для ин = 0 По КоличествоОбъектов-1 Цикл
		
		Если Объекты[ин].Выполнено = Ложь И Объекты[ин].Ошибка = Ложь Тогда
                        // readyState = 4 - признак того, что страница загружена полностью
			Если (Объекты[ин].Объект.readyState <> 4) Тогда 	
				Попытка
					// время ожидания
					Объекты[ин].Объект.waitForResponse(50);
				Исключение
					// наиболее вероятная ошибка - сработал таймаут
					Объекты[ин].Ошибка = Истина;
				КонецПопытки;
			Иначе
				// результат получен
				Объекты[ин].Выполнено = Истина;
			КонецЕсли;
		Иначе
			ОбработаноОбъектов = ОбработаноОбъектов + 1;
		КонецЕсли;
		
	КонецЦикла;
	// выходим из цикла, так как все запросы обработаны
	Если ОбработаноОбъектов = КоличествоОбъектов Тогда
		Прервать;
	КонецЕсли;	
КонецЦикла

Пример реализации для WinHttpRequest, ключевое отличие в том, что в нем нет параметра readyState, результат операции возвращает метод WaitForResponse.

Для ин = 0 По КоличествоОбъектов-1 Цикл
	
	ОбъектHTTP = Новый COMObject("WinHttp.WinHttpRequest.5.1");		
	ОбъектHTTP.Open("GET", "https://msdn.microsoft.com/ru-ru/library/ms" + Формат(762278 + ин, "ЧГ=") + "(v=vs.85).aspx", 1);
	ОбъектHTTP.Send();
	ОбъектHTTP.SetTimeouts(30000, 30000, 30000, 30000);
	Данные = Новый Структура("Объект, Выполнено, Ошибка", ОбъектHTTP, Ложь, Ложь);
	Объекты.Добавить(Данные);			
	
КонецЦикла;

// ожидание ответов	
Пока Истина Цикл
	
	ОбработаноОбъектов = 0;
	Для ин = 0 По КоличествоОбъектов-1 Цикл
		
		Если Объекты[ин].Выполнено = Ложь И Объекты[ин].Ошибка = Ложь Тогда
			
			Результат = Ложь;
			
				Попытка
					// время ожидания, в данном случае не существенно
					Результат = Объекты[ин].Объект.WaitForResponse(50);
				Исключение
					// наиболее вероятная ошибка - сработал таймаут
					Объекты[ин].Ошибка = Истина;
				КонецПопытки;
				
			Если Результат = Истина Тогда
				// результат получен
				Объекты[ин].Выполнено = Истина;
			КонецЕсли;
		Иначе
			ОбработаноОбъектов = ОбработаноОбъектов + 1;				
		КонецЕсли;
		
	КонецЦикла;
	
	Если ОбработаноОбъектов = КоличествоОбъектов Тогда
		Прервать;
	КонецЕсли;
	
КонецЦикла;

Результаты: при синхронной работе (3-ий параметр Ложь в функции open) получаем 42 сек, при параллельной работе  получаем 3 сек.  Результаты ответов одинаковые.

http асинхронность Msxml2.ServerXMLHTTP WinHttp.WinHttpRequest

См. также

SALE! 20%

Infostart Toolkit: Инструменты разработчика 1С 8.3 на управляемых формах

Инструментарий разработчика Роли и права Запросы СКД Платформа 1С v8.3 Управляемые формы Запросы Система компоновки данных Конфигурации 1cv8 Платные (руб)

Набор инструментов программиста и специалиста 1С для всех конфигураций на управляемых формах. В состав входят инструменты: Консоль запросов, Консоль СКД, Консоль кода, Редактор объекта, Анализ прав доступа, Метаданные, Поиск ссылок, Сравнение объектов, Все функции, Подписки на события и др. Редактор запросов и кода с раскраской и контекстной подсказкой. Доработанный конструктор запросов тонкого клиента. Продукт хорошо оптимизирован и обладает самым широким функционалом среди всех инструментов, представленных на рынке.

13000 10400 руб.

02.09.2020    121603    670    389    

711

Для чего используют конструкцию запроса "ГДЕ ЛОЖЬ" в СКД на примере конфигурации 1С:ERP

Запросы СКД Платформа 1С v8.3 Запросы Система компоновки данных 1С:ERP Управление предприятием 2 Бесплатно (free)

В типовых конфигурациях разработчики компании 1С иногда используют в отчетах, построенных на СКД, такую конструкцию, как "ГДЕ ЛОЖЬ". Такая конструкция говорит о том, что данные в запросе не будут получены совсем. Для чего же нужен тогда запрос?

13.02.2024    5740    KawaNoNeko    23    

23

Набор-объект для СКД по тексту или запросу

Запросы СКД Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Абонемент ($m)

Есть список полей в виде текста, или запрос - закидываем в набор СКД.

1 стартмани

31.01.2024    2000    2    Yashazz    0    

29

Запрос 1С copilot

Инструментарий разработчика Запросы Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Абонемент ($m)

Пишем на человеческом языке, что нам надо, и получаем текст запроса на языке 1С. Используются большие языковые модели (LLM GPT) от OpenAI или Яндекс на выбор.

5 стартмани

15.01.2024    6279    30    mkalimulin    25    

49

PrintWizard: поддержка представлений ЗУП в конструкторе

Инструментарий разработчика Запросы Платформа 1С v8.3 Бесплатно (free)

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

14.12.2023    1741    vandalsvq    7    

29

Объектная модель запроса "Схема запроса" 2

Запросы Платформа 1С v8.3 Запросы Конфигурации 1cv8 Бесплатно (free)

Далеко уже не новый тип данных "Схема запроса". Статья о том, как использовать его "попроще". Примеры создания текста запроса с нуля и изменение имеющегося запроса.

06.12.2023    5385    user1923546    26    

43

Начните уже использовать хранилище запросов

HighLoad оптимизация Запросы

Очень немногие из тех, кто занимается поддержкой MS SQL, работают с хранилищем запросов. А ведь хранилище запросов – это очень удобный, мощный и, главное, бесплатный инструмент, позволяющий быстро найти и локализовать проблему производительности и потребления ресурсов запросами. В статье расскажем о том, как использовать хранилище запросов в MS SQL и какие плюсы и минусы у него есть.

11.10.2023    16166    skovpin_sa    14    

98
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. tindir 05.04.17 04:30 Сейчас в теме
Я думал о фоновых заданиях, когда видел эту задачу на бирже. Использование КОМа "некросплатформеннна" =)
BigB; GreenDragon; vano-ekt; +3 Ответить
2. gzharkoj 502 05.04.17 06:28 Сейчас в теме
(1) В файловом варианте фоновые задачи будут последовательно выполняться. Ну а если необходимо еще кроссплатформенность, то без подключаемой компоненты не обойтись.
3. tindir 05.04.17 07:41 Сейчас в теме
Да, не "универсальненок" с фоновыми выходит. Возможно такое разрулит только компонента. Хотя можно заиспользовать AJAX технологию (которая потребует только наличие HTML поля и JS библиотеки, если я опять не туплю =) ).
4. gzharkoj 502 05.04.17 09:22 Сейчас в теме
(3) По факту тоже самое получиться, на JS запустите все, что нужно, а 1С также будет висеть и ожидать результата, только время потратите больше на реализацию. Это по идее можно сделать через HTML-поле и XMLHttpRequest под Win, а вот под Linux как организовать не могу сказать, не занимался этим вопросом.
6. TitanLuchs 395 05.04.17 09:54 Сейчас в теме
(4)
XMLHttpRequest под Win

Вчера как раз проверяли на WinHttpRequest - 2200 запросов за 1 минуту отработало отлично. Это больше 30 в секунду.
7. gzharkoj 502 05.04.17 10:06 Сейчас в теме
(6) На всякий случай замечу, что скорость будет зависеть от запрашиваемого ресурса и линий связи.
8. TitanLuchs 395 05.04.17 10:12 Сейчас в теме
(7) Скорость ответа - да, а скорость генерации запросов - вряд ли. Я же не писал, что на все эти запросы и ответы пришли в течение минуты. WinHttp помогает в том смысле, что позволяет добиться асинхронности на файловой базе, а так - толку от нее не больше, чем от встроенных механизмов платформы.
9. gzharkoj 502 05.04.17 10:26 Сейчас в теме
(8) Я подумал, что речь идет о завершенных операциях. Так весь смысл в том, чтобы более/менее универсально было вне зависимости от архитектуры, получается, что толк есть!
10. TitanLuchs 395 05.04.17 10:37 Сейчас в теме
(9)
Я подумал, что речь идет о завершенных операциях

Нет, конечно. Мы бомбили собственный достаточно слабый сервер, там пара запросов вернули ответ через 22 секунды.
Наличие толка - вещь субъективная, зависит от многих переменных. Вполне возможно, что где-то это будет наилучшим решением.
gzharkoj; +1 Ответить
5. tindir 05.04.17 09:50 Сейчас в теме
Так это и имеется в виду. HTML работает почти одинаково в ВИНЬ и ЛИНЬ. Мы циклом кидаем XMLHttpRequest в асинхронном или обещанном режиме и ждем пока нам вернутся все события, причем в этот момент 1ц не будет виснуть, тк исполняется реквест в другой программе.
Или я не до конца понимаю и JS методологию?=)
11. Serginio 938 05.04.17 10:45 Сейчас в теме
Вообще то есть вариант без регистрации и кроссплатформенный
Асинхронное программирование в 1С через использование классов .Net из Native ВК
Inkasor; vano-ekt; +2 Ответить
12. sashs1980 85 05.04.17 12:00 Сейчас в теме
Вот тут ошибку исправьте
ОбъектHTTP.Open("GET", "https://msdn.microsoft.com/ru-ru/library/ms" + Формат(762278 + 0, "ЧГ=") + "(v=vs.85).aspx", 1);
13. gzharkoj 502 05.04.17 14:48 Сейчас в теме
14. kiruha 388 17.04.17 19:20 Сейчас в теме
А если идет обращение к веб-сервису другой базы 1С(на SQL) - будет параллельное, или в очередь встанут ?
15. gzharkoj 502 17.04.17 19:45 Сейчас в теме
Там каждый раз создается объект, его состояние на другие не распространяется. Web-сервер, на котором развернут сервис 1С, по идее создаст столько процессов 1С сколько запрос пришло, поэтому не должно ничего вставать в очередь.
16. azubar 45 09.05.17 19:07 Сейчас в теме
Добавлю что на фоновых будет ресурсов жрать уйму... писал парсер на фоновых заданиях 1С, в итоге переписал парсер на php + api для импорта данных в 1С, все стало работать гораздо быстрее не говоря уже об экономии ресурсов.
17. echo77 1868 13.06.17 21:15 Сейчас в теме
Глупый вопрос - что дальше делать, с полученным в массиве объектом? Можно ли картинки так загружать и как их сохранить?
18. gzharkoj 502 14.06.17 07:20 Сейчас в теме
(17) Например, в каждом объекте для WinHttp.WinHttpRequest будет свойство responseText, в которое содержит то, что вернул сайт/сервис. Если же запросили какие-то двоичные данные (картинка, документы и т.д.), то результат будет в свойстве ResponseBody, обработать это поможет другой объект ADODB.Stream. В сети найдете много примеров, можете и мой посмотреть, там как раз описанная связка используется http://infostart.ru/public/538345/
19. echo77 1868 14.06.17 07:57 Сейчас в теме
(18) Спасибо большое! Все понятно, все получилось.
Оставьте свое сообщение