Параллельные 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

См. также

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

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

12000 руб.

02.09.2020    169261    937    403    

905

Запросы Программист Бесплатно (free)

Увидел cheatsheet по SQL и захотелось нарисовать подобное, но про запросы.

18.10.2024    11392    sergey279    18    

65

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

Столкнулся с интересной ситуацией, которую хотел бы разобрать, ввиду её неочевидности. Речь пойдёт про использование функции запроса АВТОНОМЕРЗАПИСИ() и проблемы, которые могут возникнуть.

11.10.2024    6338    XilDen    36    

83

Запросы Программист Запросы Бесплатно (free)

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

16.08.2024    9066    user1840182    5    

28

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

Рассмотрим быстрый алгоритм поиска дублей с использованием hash функции по набору полей шапки и табличных частей.

08.07.2024    2727    ivanov660    9    

22

Запросы СКД Программист Стажер Система компоновки данных Россия Бесплатно (free)

Часто при разработке отчетов в СКД возникает ситуация, когда не совсем понятно, почему отчет выводит не те данные, которые нужны, либо не выводит вовсе. Возникает потребность увидеть конечный запрос, который формирует СКД. Как это сделать, рассмотрим в этой статье.

15.05.2024    10219    implecs_team    6    

48

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

Часто поступают задачи по произвольному распределению общих сумм. После распределения иногда пропадают копейки. Суть решения добавить АвтоНомерЗаписи() в ВТ распределения, и далее используя функции МАКСИМУМ или МИНИМУМ можем положить разницу копеек в первую или последнюю строку знаменателя распределения.

11.04.2024    3623    andrey_sag    10    

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

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

Нет, конечно. Мы бомбили собственный достаточно слабый сервер, там пара запросов вернули ответ через 22 секунды.
Наличие толка - вещь субъективная, зависит от многих переменных. Вполне возможно, что где-то это будет наилучшим решением.
gzharkoj; +1 Ответить
5. tindir 05.04.17 09:50 Сейчас в теме
Так это и имеется в виду. HTML работает почти одинаково в ВИНЬ и ЛИНЬ. Мы циклом кидаем XMLHttpRequest в асинхронном или обещанном режиме и ждем пока нам вернутся все события, причем в этот момент 1ц не будет виснуть, тк исполняется реквест в другой программе.
Или я не до конца понимаю и JS методологию?=)
11. Serginio 941 05.04.17 10:45 Сейчас в теме
Вообще то есть вариант без регистрации и кроссплатформенный
Асинхронное программирование в 1С через использование классов .Net из Native ВК
Inkasor; vano-ekt; +2 Ответить
12. sashs1980 86 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 521 05.04.17 14:48 Сейчас в теме
14. kiruha 388 17.04.17 19:20 Сейчас в теме
А если идет обращение к веб-сервису другой базы 1С(на SQL) - будет параллельное, или в очередь встанут ?
15. gzharkoj 521 17.04.17 19:45 Сейчас в теме
Там каждый раз создается объект, его состояние на другие не распространяется. Web-сервер, на котором развернут сервис 1С, по идее создаст столько процессов 1С сколько запрос пришло, поэтому не должно ничего вставать в очередь.
16. azubar 49 09.05.17 19:07 Сейчас в теме
Добавлю что на фоновых будет ресурсов жрать уйму... писал парсер на фоновых заданиях 1С, в итоге переписал парсер на php + api для импорта данных в 1С, все стало работать гораздо быстрее не говоря уже об экономии ресурсов.
17. echo77 1913 13.06.17 21:15 Сейчас в теме
Глупый вопрос - что дальше делать, с полученным в массиве объектом? Можно ли картинки так загружать и как их сохранить?
18. gzharkoj 521 14.06.17 07:20 Сейчас в теме
(17) Например, в каждом объекте для WinHttp.WinHttpRequest будет свойство responseText, в которое содержит то, что вернул сайт/сервис. Если же запросили какие-то двоичные данные (картинка, документы и т.д.), то результат будет в свойстве ResponseBody, обработать это поможет другой объект ADODB.Stream. В сети найдете много примеров, можете и мой посмотреть, там как раз описанная связка используется http://infostart.ru/public/538345/
19. echo77 1913 14.06.17 07:57 Сейчас в теме
(18) Спасибо большое! Все понятно, все получилось.
Оставьте свое сообщение