Передача большого количества объектов через Web-сервисы

31.01.17

Интеграция - WEB-интеграция

Один из вариантов передачи большого количества объектов при использовании Web-сервисов.

Скачать файл

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Наименование По подписке [?] Купить один файл
КонвертацияОбъектовИнформационныхБаз
.epf 116,77Kb
7
7 Скачать (1 SM) Купить за 1 850 руб.

Дисклеймер

Сразу хочу оговориться, что ниже написанное не претендует на лучшее решение (возможно, код где-то не оптимален), это просто как один из вариантов решения возникшей проблемы. 

Вместо введения 

Собственно, что мы имеем - имеем две конфигурации, одна написанная с нуля для работы кассиров в магазинах, так называемый FrontOffice, вторая Управление торговлей, редакция 11.2 (11.2.3.108). В обе конфигурации встроена БСП версии 2.3.2.50.  Между конфигурациями существует обмен данными через Web-сервисы. Сам обмен и транспорт обмена полностью типовой, добавлен только свой план обмена. Обмен между базами происходит раз в 5 минут и в среднем очень маленький, в пределах 100 - 150 объектов за одну итерацию. Ввиду того что обмен работает через Web-сервис а магазины (FrontOffice) географически находятся в разных местах мы имеем несколько ограничений. Первое ограничение связано с тем что с разными магазинами (FrontOffice) разные каналы связи, которые соответственно имеют разную пропускную способность (от 2 Мбит до 50 Мбит), что в свою очередь накладывает серьезные ограничения на передаваемый объем данных. Второе ограничения связано с передачей данных на стороне веб сервера. Как пишут в статьях и на форумах максимальный размер пакета, который стабильно может передаваться через веба сервер варьируется от 16 Мб до 30 Мб (при настройках по умолчанию в зависимости от Web-сервера).  По факту, ради эксперимента, я передавал файл через Web-сервис размером примерно 130 Мб в локальной сети, и он проходил, без каких-либо доработок, но не понятно, как это сказывалось на работоспособности веб сервера (так как не рекомендуется передавать данные больше нескольких Мб) и как бы это все происходило при пропускной способности канала 2 Мбита.

О проблеме 

Суть проблемы заключается в том, что в определённый момент времени нужно передать порядка> 60000 объектов + примерно 40000 объектов должны были выгрузиться по ссылкам. При попытке выгрузить такое количество данных на магазин с пропускной способностью канала в 50 Мбит происходило следующее. План обмена на стороне инициатора обмена показывал, что все данные успешно выгружены, не сжатый файл выгрузки при этом "весил" примерно 800 Мб в сжатом виде примерно 13 Мб. А на принимающей стороне отображалось информация о том, что ничего не происходит и весь журнал регистрации заполнялся ошибками, т.к. обмен пытался каждые 5 минут запуститься заново, но не запускался из-за ошибки, что уже идет обмен данными. Так могло продолжаться пол дня и сутки и ничего в итоге не загружалось, обмен просто подвисал. По идее, при передачи данных через web-сервис (если верить исходному коду и описанию) происходит разбивка выгружаемых данные на файлы примерно по 1 Мб их передача, а затем склеивание и загрузка. Происходит это в общем модуле ОбменДаннымиСервер:

// Функция передает указанный файл в сервис передачи файлов.
//
// Параметры:
//  ИмяФайла                 - Строка - путь к передаваемому файлу.
//  ПараметрыДоступаКСервису - Структура: АдресСервиса, ИмяПользователя, ПарольПользователя. 
//  РазмерЧасти              - Число - размер части в килобайтах. Если значение равно 0,
//                             то разбивка на части не производится.
// Возвращаемое значение:
//  УникальныйИдентификатор  - идентификатор файла в сервисе передачи файлов.
//
Функция ПоместитьФайлВХранилищеВСервисе(Знач ИмяФайла, Знач УзелИнформационнойБазы, Знач РазмерЧасти = 1024, Знач ПараметрыАутентификации = Неопределено)
	
	// Возвращаемое значение функции.
	ИдентификаторФайла = Неопределено;
	
	Прокси = ПолучитьWSПроксиДляУзлаИнформационнойБазы(УзелИнформационнойБазы,, ПараметрыАутентификации);
	
	ОбменВыполняетсяВОднойСети = ОбменДаннымиПовтИсп.ОбменВыполняетсяВОднойЛокальнойСети(УзелИнформационнойБазы, ПараметрыАутентификации);
	
	Если ОбменВыполняетсяВОднойСети Тогда
		
		ИмяФайлаВХранилище = ОбщегоНазначенияКлиентСервер.ПолучитьПолноеИмяФайла(КаталогВременногоХранилищаФайлов(), УникальноеИмяФайлаСообщенияОбмена());
		
		ПереместитьФайл(ИмяФайла, ИмяФайлаВХранилище);
		
		Прокси.PutFileIntoStorage(ИмяФайлаВХранилище, ИдентификаторФайла);
		
	Иначе
		
		КаталогФайлов = ПолучитьИмяВременногоФайла();
		СоздатьКаталог(КаталогФайлов);
		
		// Архивирование файла
		ИмяНеразделенногоФайла = ОбщегоНазначенияКлиентСервер.ПолучитьПолноеИмяФайла(КаталогФайлов, "data.zip");
		Архиватор = Новый ЗаписьZipФайла(ИмяНеразделенногоФайла,,,, УровеньСжатияZIP.Максимальный);
		Архиватор.Добавить(ИмяФайла);
		Архиватор.Записать();
		
		// Разделение файла на части
		ИдентификаторСессии = Новый УникальныйИдентификатор;
		
		КоличествоЧастей = 1;
		Если ЗначениеЗаполнено(РазмерЧасти) Тогда
			ИменаФайлов = РазделитьФайл(ИмяНеразделенногоФайла, РазмерЧасти * 1024);
			КоличествоЧастей = ИменаФайлов.Количество();
			Для НомерЧасти = 1 По КоличествоЧастей Цикл
				ИмяФайлаЧасти = ИменаФайлов[НомерЧасти - 1];
				ДанныеФайла = Новый ДвоичныеДанные(ИмяФайлаЧасти);
				Прокси.PutFilePart(ИдентификаторСессии, НомерЧасти, ДанныеФайла);
			КонецЦикла;
		Иначе
			ДанныеФайла = Новый ДвоичныеДанные(ИмяНеразделенногоФайла);
			Прокси.PutFilePart(ИдентификаторСессии, 1, ДанныеФайла);
		КонецЕсли;
		
		Попытка
			УдалитьФайлы(КаталогФайлов);
		Исключение
			ЗаписьЖурналаРегистрации(СобытиеЖурналаРегистрацииУдалениеВременногоФайла(),
				УровеньЖурналаРегистрации.Ошибка,,, ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		КонецПопытки;
		
		Прокси.SaveFileFromParts(ИдентификаторСессии, КоличествоЧастей, ИдентификаторФайла);
		
	КонецЕсли;
	
	Возврат ИдентификаторФайла;
КонецФункции

Да и действительно файл разбивается на части, в случае если он больше 1 Мб и передается, но в нашем случае данные метод не помогает, обмен все равно зависает, где то при попытке все эти данные передать и загрузить. Тогда в общем то и родилась идея передавать данные частями, а точнее выгружать определённое количество объектов за одну итерацию обмена данными. К примеру, если зарегистрировано 10000 изменений по справочникам мы их выгружаем по 1000 за одну итерацию обмена, пока не выгрузим все 10000 объектов. Тем самым мы уменьшаем нагрузку на канал, уменьшаем время выгрузки и загрузки за одну итерацию и в общем если канал связи совсем слабый, то гарантированно передаем необходимое количество данных за раз. Идея реализации была в том, чтобы выгрузка продолжала работать через типовые средства при помощи БСП, но в случае необходимости, делала это частями.

Реализация

Собственно, сам алгоритм получился примерно следующий:

Блок схема

  1. Сначала проверяем количество зарегистрированных объектов (наборов записей) на целевом плане обмена и соответственно узле. Если количество объектов меньше чем установлено в ограничении, то никаких дополнительных ограничений не накладываем, просто выгружаем все как есть типовыми механизмами.
  2. Если количество зарегистрированных изменений по справочникам больше чем установлено в ограничении, то сначала порционно выгружаются данные из справочников. Справочники выгружаются в первую очередь, чтобы между выгрузкой справочников и регистров в регистрах не было «Объект не найден»
  3. Если количество зарегистрированных объектов больше чем установлено в ограничении и есть зарегистрированные изменения по регистрам, то порционно выгружаются регистры (сведений и накоплений).

Может возникнуть вопрос, почему не выгружать одновременно справочники и регистры, если количество зарегистрированных изменений не превышает ограничение. Ответ кроется в функции ВыбратьИзменения у менеджера плана обмена. Что она собственно делает? Описание из синтаксис помощника 1С:Предприятие:

Синтаксис:

ВыбратьИзменения(<Узел>, <НомерСообщения>, <ФильтрВыборки>)

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

В чем ее смысл – она выбирает измененные данные (зарегистрированные изменения) и проставляет в записи регистрации изменений номер сообщения обмена данными. Нам же нужно ограничить выборку определенным количеством объектов. В описании к данной функции есть важное замечание к 3 параметру «ФильтрВыборки»:

Неопределено - фильтр пуст, выбираются все изменения по узлу;
ОбъектМетаданных - выбираются изменения в основной таблице, связанной с данным объектом метаданных;
СсылкаНаОбъект - фактически, может быть выбрана только одна запись об изменении данного объекта, либо ни одной, если объект не менялся;
НаборЗаписей - набор записей регистра, может быть не выбран, для фильтрации изменений используется лишь отбор набора записей;
Массив - все элементы массива имеют один из перечисленных выше типов, кроме Неопределено. Условия фильтрации соединяются по ИЛИ.
Значение по умолчанию: Неопределено.

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

Все изменения добавляются в обработку «КонвертацияОбъектовИнформационныхБаз» в модуль объекта в процедуру «ВыполнитьВыгрузкуЗарегистрированныхДанных» после строки:

«НачальнаяВыгрузкаДанных = ОбменДаннымиСервер.УстановленПризнакНачальнойВыгрузкиДанных(ЗаписьСообщения.Получатель);»

До строки кода, которую тоже необходимо заменить:

ВыборкаИзменений = ОбменДаннымиСервер.ВыбратьИзменения(ЗаписьСообщения.Получатель, ЗаписьСообщения.НомерСообщения, МассивВыгружаемыхМетаданных);  

В планы обмена необходимо добавить реквизит "КоличествоОбъектовВыгрузки" с типом число и добавить его на форму, в тем планы обмена, где ограничение актуально.

Еще один важный и приятный нюанс, это то что код написан таким образом, что при изменении состава необходимого плана обмена, нет необходимости переписывать ниже приведенный код, т.к. в нем определяется входит ли в состав плана обмена измененный объект. Т.е. в случае добавления нового объекта в состав плана обмена (или исключение), он будет автоматически добавляться (не добавляться, в случае исключения) в динамически формируемые запросы.

Собственно, сам код с комментариями.

//Проверка на ограничение выгрузки данных за одну итерацию обмена данных
//=======================================================================
//получаем значение установленного ограничения
КоличествоОбъектовКВыгрузке = ЗаписьСообщения.Получатель.КоличествоОбъектовВыгрузки;
//если ограничение установлено, то начинаем собирать запрос по объектам участвующим в обмене
Если КоличествоОбъектовКВыгрузке <> 0 Тогда
    МассивДанныхДляОтбора = Новый Массив;
    ТекущийПланОбмена = Метаданные.ПланыОбмена[ЗаписьСообщения.Получатель.Метаданные().Имя];
    
    ТекстЗапросаОбщий = "";
    
    Для каждого СтрокаМетаданных Из ТаблицаПравилВыгрузкиИспользуемые Цикл
        СтрокаДляЗапроса = "";
        //для справочников формируем запрос с учетом того что там всегда есть Ссылка
        Если ЗначениеЗаполнено(СтрокаМетаданных.ИмяОбъектаДляЗапроса) И ТипЗнч(ТекущийПланОбмена.Состав.Найти(СтрокаМетаданных.ОбъектВыборкиМетаданные)) = Тип("ЭлементСоставаПланаОбмена") Тогда
            СтрокаДляЗапроса = СтрокаМетаданных.ИмяОбъектаДляЗапроса;
            
            //если это первый проход то указываем что это создание пакета
            Если ТекстЗапросаОбщий = "" Тогда
                ТекстЗапросаОбщий = ТекстЗапросаОбщий + "Выбрать ВД.Ссылка" + Символы.ПС + "ПОМЕСТИТЬ ВсеДанные" + Символы.ПС + " из " + СтрокаДляЗапроса + ".Изменения" + " КАК ВД ГДЕ ВД.Узел = &Узел" + Символы.ПС;
            Иначе
                ТекстЗапросаОбщий = ТекстЗапросаОбщий + "ОБЪЕДИНИТЬ ВСЕ" + Символы.ПС + "Выбрать ВД.Ссылка из " + СтрокаДляЗапроса + ".Изменения" + " КАК ВД ГДЕ ВД.Узел = &Узел" + Символы.ПС;
            КонецЕсли;
            
            //для регистров формируем запрос с учетом того что там разный набор измерений, но нам достаточно бырать Узел, чтобы подсчитать Количество объектов
            Если ЗначениеЗаполнено(СтрокаМетаданных.ИмяОбъектаДляЗапросаРегистра) И ТипЗнч(ТекущийПланОбмена.Состав.Найти(СтрокаМетаданных.ОбъектВыборкиМетаданные)) = Тип("ЭлементСоставаПланаОбмена") Тогда
                СтрокаДляЗапроса = СтрокаМетаданных.ИмяОбъектаДляЗапросаРегистра;
                //если это первый проход то указываем что это создание пакета
                Если ТекстЗапросаОбщий = "" Тогда
                    ТекстЗапросаОбщий = ТекстЗапросаОбщий + "ВЫБРАТЬ ПЕРВЫЕ " + Формат(КоличествоОбъектовКВыгрузке, "ЧГ=0") + " Узел ПОМЕСТИТЬ ВсеДанные ИЗ " + СтрокаДляЗапроса + ".Изменения ГДЕ Узел = &Узел";
                Иначе
                    ТекстЗапросаОбщий = ТекстЗапросаОбщий + "ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ПЕРВЫЕ " + Формат(КоличествоОбъектовКВыгрузке, "ЧГ=0") + " Узел ИЗ " + СтрокаДляЗапроса + ".Изменения ГДЕ Узел = &Узел";
                КонецЕсли;
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;
    
    //добавляем выборку данных
    ТекстЗапросаОбщий = ТекстЗапросаОбщий + Символы.ПС + "; ВЫБРАТЬ ПЕРВЫЕ " + Формат(КоличествоОбъектовКВыгрузке, "ЧГ=0") +
        " ВсеДанные.Ссылка КАК ИзмененныйОбъект ИЗ ВсеДанные КАК ВсеДанные";
    
    ЗапросПоИзмененнымОбъектам = Новый Запрос(ТекстЗапросаОбщий);
    ЗапросПоИзмененнымОбъектам.УстановитьПараметр("Узел", ЗаписьСообщения.Получатель);
    ВыборкаПоИзмененнымОбъектам = ЗапросПоИзмененнымОбъектам.Выполнить().Выбрать();
    
    //получаем количество измененных объектов, которое в любом случае не будет больше ограничения, тем самым ускоряя выборку и проверку
    КоличествоЗарегистрированныхИзменений = ВыборкаПоИзмененнымОбъектам.Количество();
    
    //если количество зарегистрированных объектов = количеству объектов ограничения то нуобходимо ограничить выгрузку
    //проверка на "=" потому что все выборки ограничиваются количеством указанным в ограничении
    //или есди по справочникам не зарегистрировано изменений, то выгружаем РС если по ним есть что выгрузить
    Если КоличествоЗарегистрированныхИзменений = КоличествоОбъектовКВыгрузке ИЛИ КоличествоЗарегистрированныхИзменений = 0 Тогда
        //собираем запрос по изменениям из справочников
        ТекстЗапросаПоСправочникам = "";
        
        Для каждого СтрокаМетаданных Из ТаблицаПравилВыгрузкиИспользуемые Цикл
            СтрокаДляЗапроса = "";
            Если ЗначениеЗаполнено(СтрокаМетаданных.ИмяОбъектаДляЗапроса) И ТипЗнч(ТекущийПланОбмена.Состав.Найти(СтрокаМетаданных.ОбъектВыборкиМетаданные)) = Тип("ЭлементСоставаПланаОбмена") Тогда
                СтрокаДляЗапроса = СтрокаМетаданных.ИмяОбъектаДляЗапроса;
                
                Если ТекстЗапросаПоСправочникам = "" Тогда
                    ТекстЗапросаПоСправочникам = ТекстЗапросаПоСправочникам + "Выбрать ПЕРВЫЕ " + Формат(КоличествоОбъектовКВыгрузке, "ЧГ=0") + " ВД.Ссылка" + Символы.ПС + "ПОМЕСТИТЬ ВсеДанные" + Символы.ПС + " из " + СтрокаДляЗапроса + ".Изменения" + " КАК ВД ГДЕ ВД.Узел = &Узел" + Символы.ПС;
                Иначе
                    ТекстЗапросаПоСправочникам = ТекстЗапросаПоСправочникам + "ОБЪЕДИНИТЬ ВСЕ" + Символы.ПС + "Выбрать ПЕРВЫЕ " + Формат(КоличествоОбъектовКВыгрузке, "ЧГ=0") + " ВД.Ссылка из " + СтрокаДляЗапроса + ".Изменения" + " КАК ВД ГДЕ ВД.Узел = &Узел" + Символы.ПС;
                КонецЕсли;
            КонецЕсли;
        КонецЦикла;
        //добавляем выборку данных
        ТекстЗапросаПоСправочникам = ТекстЗапросаПоСправочникам + "; ВЫБРАТЬ ПЕРВЫЕ " + Формат(КоличествоОбъектовКВыгрузке, "ЧГ=0") + " ВД.Ссылка ИЗ ВсеДанные КАК ВД";
        ЗапросПоИзмененнымДанным = Новый Запрос(ТекстЗапросаПоСправочникам);
        ЗапросПоИзмененнымДанным.УстановитьПараметр("Узел", ЗаписьСообщения.Получатель);
        
        //получаем данные с учетом ограничения которые будем выгружать
        МассивДанныхДляОтбора = ЗапросПоИзмененнымДанным.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка");
        
        //запоминаем сколько объектов всего выгрузили
        ВсегоВыгружено = МассивДанныхДляОтбора.Количество();
        
        ТекстЗапросаПоРегистрам = "";
        
        //если не было выгрузки справочников то в этой итерации можно выгрузить регистры
        Если ВсегоВыгружено = 0 Тогда
            Для каждого СтрокаМетаданных Из ТаблицаПравилВыгрузкиИспользуемые Цикл
                //собираем запрос по изменениям из регистров
                СтрокаДляЗапроса = "";
                
                Если КоличествоОбъектовКВыгрузке - ВсегоВыгружено = 0 Тогда
                    Прервать;
                КонецЕсли;
                
                Если ЗначениеЗаполнено(СтрокаМетаданных.ИмяОбъектаДляЗапросаРегистра) И ТипЗнч(ТекущийПланОбмена.Состав.Найти(СтрокаМетаданных.ОбъектВыборкиМетаданные)) = Тип("ЭлементСоставаПланаОбмена") Тогда
                    СтрокаДляЗапроса = СтрокаМетаданных.ИмяОбъектаДляЗапросаРегистра;
                    
                    ТекстЗапросаПоРегистрам = "ВЫБРАТЬ ПЕРВЫЕ " + Формат((КоличествоОбъектовКВыгрузке - ВсегоВыгружено), "ЧГ=0") + " * ИЗ " + СтрокаДляЗапроса + ".Изменения ГДЕ Узел = &Узел";
                    
                    Запрос = Новый Запрос(ТекстЗапросаПоРегистрам);
                    Запрос.УстановитьПараметр("Узел", ЗаписьСообщения.Получатель);
                    ИзмененныеДанные = Запрос.Выполнить().Выбрать();
                    
                    Если ИзмененныеДанные.Количество() > 0 Тогда
                        Пока ИзмененныеДанные.Следующий() Цикл
                            Если ВсегоВыгружено = КоличествоОбъектовКВыгрузке Тогда
                                Прервать;
                            КонецЕсли;
                            
                            //формируем пустые наборы записей, т.к. из них нужны отборы для корректной фильтрации данных
                            Если Найти(СтрокаДляЗапроса, "РегистрСведений") <> 0 Тогда
                                Набор = РегистрыСведений[СтрЗаменить(СтрокаДляЗапроса, "РегистрСведений.", "")].СоздатьНаборЗаписей();
                            ИначеЕсли Найти(СтрокаДляЗапроса, "РегистрНакопления") <> 0 Тогда
                                Набор = РегистрыНакопления[СтрЗаменить(СтрокаДляЗапроса, "РегистрНакопления.", "")].СоздатьНаборЗаписей();
                            КонецЕсли;
                            
                            //заполняем отборы данных в зависимости от измерения конкретного регистра
                            Для каждого СтрокаОтбора Из Набор.Отбор Цикл
                                //Добавляем попытку, т.к. в выборке из запроса могут быть не все поля, которое есть в отборе набора
                                Попытка
                                    СтрокаОтбора.Установить(ИзмененныеДанные[СтрокаОтбора.ПутьКДанным]);
                                Исключение
                                КонецПопытки;
                            КонецЦикла;
                            
                            МассивДанныхДляОтбора.Добавить(Набор);
                            
                            Инкремент(ВсегоВыгружено);
                        КонецЦикла;
                    КонецЕсли;
                    
                КонецЕсли;
                
            КонецЦикла;
            
        КонецЕсли;
        //=======================================================================
        // ВЫБОРКА ИЗМЕНЕНИЙ
        ВыборкаИзменений = ОбменДаннымиСервер.ВыбратьИзменения(ЗаписьСообщения.Получатель, ЗаписьСообщения.НомерСообщения, МассивДанныхДляОтбора);
    Иначе
        // если количество объектов справочников к выгрузке меньше ограничения, то выгружаем только справочники, т.к. по регистрам
        // может быть Количество объктов к выгрузке большем чем ограничение
        МассивМетаданныхСправочников = ТаблицаПравилВыгрузкиИспользуемые.НайтиСтроки(Новый Структура("ИмяОбъектаДляЗапросаРегистра", Неопределено));
        МассивВыгружаемыхМетаданных = Новый Массив;
        Для каждого СтрокаМассиваМетаданныхСправочников Из МассивМетаданныхСправочников Цикл
            МассивВыгружаемыхМетаданных.Добавить(СтрокаМассиваМетаданныхСправочников.ОбъектВыборкиМетаданные);
        КонецЦикла;
        
        ВыборкаИзменений = ОбменДаннымиСервер.ВыбратьИзменения(ЗаписьСообщения.Получатель, ЗаписьСообщения.НомерСообщения, МассивВыгружаемыхМетаданных);
    КонецЕсли;
Иначе
    ВыборкаИзменений = ОбменДаннымиСервер.ВыбратьИзменения(ЗаписьСообщения.Получатель, ЗаписьСообщения.НомерСообщения, МассивВыгружаемыхМетаданных);
КонецЕсли;

Про быстродействие

В целом, добавление данного кода не должно вызывать какие то-провалы в производительности выборки данных для выгрузки. Все выборки из запросов ограничиваются количеством, заданным в ограничении, что позволяет не выбирать "лишние" данные, что существенно уменьшает объем выбираемых данных и увеличивает быстродействие запросов. Да и к тому же в случае ограничения выборки данных, функция "ВыбратьИзменения" с наложенным фильтром отрабатывает гораздо быстрее, чем выборка всех полностью изменений.

Ограничения

  1. Данный код проверялся только на Управление торговлей, редакция 11.2 (11.2.3.108) и БСП 2.3.2.50 и только в режиме передачи данных через Web - сервисы, по правилам, написанным в конвертации данных 2.1. Возможно в других конфигурация потребуется какая-то доработка кода, так же и в случае использования универсально формата обмена данными.
  2. Данный код рассчитан на то, что в составе плана обмена участвуют только справочники, регистры сведений и регистры накопления. Если в плане обмена участвуют другие объекты, то код потребует доработки.

Вместо заключения

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

Надеюсь данное решение поможет кому то сэкономить время в случае подобной проблемы.

Web-сервис веб - сервис

См. также

Сайты и интернет-магазины WEB-интеграция Системный администратор Программист Пользователь Платформа 1С v8.3 Конфигурации 1cv8 1С:Управление торговлей 11 Автомобили, автосервисы Россия Управленческий учет Платные (руб)

Интеграционный модуль обмена между конфигурацией Альфа Авто 5 и Альфа Авто 6 и порталом AUTOCRM. Данный модуль универсален. Позволяет работать с несколькими обменами AUTOCRM разных брендов в одной информационной базе в ручном и автоматическом режиме.

36000 руб.

03.08.2020    17941    18    22    

17

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

Интеграция 1С и Битрикс 24. Разработка имеет двухстороннюю синхронизацию 1С и Bitrix24 задачами. Решение позволяет создавать пользователя в 1С из Битрикс24 и наоборот. Данная разработка технически подходит под все основные конфигурации линейки продуктов 1С:Предприятие 8.3 (платформа начиная с 8.3.23). При приобретении предоставляется 1 месяц бесплатных обновлений разработки. Доступна демо-версия продукта с подключением Вашего Битрикс24

7200 руб.

04.05.2021    20063    13    19    

17

WEB-интеграция 8.3.8 Конфигурации 1cv8 Автомобили, автосервисы Беларусь Украина Россия Казахстан Управленческий учет Платные (руб)

Расширение предназначено для конфигурации "1С:Предприятие 8. Управление Автотранспортом. ПРОФ". Функционал модуля: 1. Заполнение регистров сведений по подсистеме "Мониторинг", а именно: события по мониторингу, координаты по мониторингу, пробег и расход по мониторингу, текущее местоположение ТС по мониторингу 2. Заполнение путевого листа: пробег по мониторингу, время выезда/заезда, табличная часть ГСМ, места стоянок по геозонам. 3. Отчеты по данным загруженным в регистры сведений. 4. Предусмотрена автоматическая загрузка данных в фоновом режиме (условия работы данной загрузке читайте в описании товара) Модуль работает без включенной константы по настройкам мониторинга. Модуль формы предоставляется с открытым кодом, общий модуль защищен. Любой заинтересованный пользователь, имеет возможность скачать демо-версию расширения.

22656 руб.

25.05.2021    14523    42    8    

18

WEB-интеграция Программист Руководитель проекта Платформа 1С v8.3 Конфигурации 1cv8 1С:Франчайзи, автоматизация бизнеса Платные (руб)

Расширение значительно упрощает написание API на 1С. Веб программисты получают простой и понятный доступ к 1С. Описание API создаётся автоматически и представляется в виде удобном как для человека, так и для программной обработки.

24000 руб.

27.09.2024    1613    1    0    

3
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. warrior1985 68 01.02.17 09:36 Сейчас в теме
3. SinglCOOLer 217 01.02.17 11:26 Сейчас в теме
2. DenisCh 01.02.17 09:43 Сейчас в теме
Я-то думал, будет что-то оригинальное...
А разбиение по кускам - это очевидное же решение...
4. SinglCOOLer 217 01.02.17 11:26 Сейчас в теме
(2) поэтому дисклеймер и написал
5. comol 5110 13.03.17 12:43 Сейчас в теме
Автор знает толк в извращениях.

Можно конечно и 60 тыс передать через web сервисы.. но зачем?

9. SinglCOOLer 217 14.03.17 11:01 Сейчас в теме
(5) Затем что есть FrontOffice на котором работают скидки и бонусы как в УТ 11, для их расчета нужно достаточно много информации
6. ipoloskov 164 13.03.17 13:08 Сейчас в теме
При решении аналогичной задачи, встал вопрос блокировки данных изменений. Как известно, план обмена блокирует таблицы изменений, начиная с операторов
ЗаписьСообщения = ПланыОбмена.СоздатьЗаписьСообщения();
ЗаписьСообщения.НачатьЗапись(ЗаписьXML, УзелОбмена); 

и заканчивая
ЗаписьСообщения.ЗакончитьЗапись(); 

после последней строчки, соответственно, план обмена начинает писать изменения с Номером+1
Оставлять все в базе заблокированным между вызовами нельзя. Как вы решили эту проблему?
7. comol 5110 13.03.17 14:25 Сейчас в теме
(6) Эх, если бы этот вопрос был решен или хоть как то решался жизнь была бы настолько проще...

Вообщем если хотим передать кучу данных - пишем их тупо в файл на ftp - самый правильный и надежный способ.
Если хотим выбрать кучу изменений - исключаем их из общего РИБ-а и выделяем в отдельный узел... ну или свой механизм регистрации пишем
Если надо чтобы "оно само" - убираем обмены и в отельную СУБД (couchDB)
8. ipoloskov 164 13.03.17 15:31 Сейчас в теме
(7) я решил так:
мне надо было передавать документы и их печатные формы. В пакете выгрузки между НачатьЗапись и ЗакончитьЗапись я выгружал только документы, без печатных форм. Документы, хотя их и много, но объем данных в выгрузке образуют небольшой. Весь образованный объем данных без труда прокачивался за один вызов.
Следующими вызовами, по частям, я запрашивал печатные формы для заданного массива документов. Там уже план обмена не используется, и ничего не блокируется.

В экстремальных случаях, если даже данные документов слишком объемны для единоразовой прокачки, можно на первом этапе выгружать и передавать только их УИДы. А все данные получать потом, частями.
11. SinglCOOLer 217 14.03.17 11:05 Сейчас в теме
(7) По моему вы как раз знаете толк в извращениях, ftp и в общем работа с файлами напрямую это лишняя и не нужная точка отказа, про РИБ вообще молчу, что то простите еще отдельную СУБД городить? Я останусь при своем мнении
12. comol 5110 14.03.17 14:53 Сейчас в теме
(11) А ограничения http протокола это не точка отказа? 6))))))))))). Будем проверять что надежнее ftp или web сервисы? :)))
13. SinglCOOLer 217 14.03.17 18:13 Сейчас в теме
(12) У нас уже все проверено, веб сервисы на бсп сами дробят файл + мы сами ограничиваем размер. Зачем нам на слабых компьютерах где работает касса грузить к примеру файл 4 гб или более? что будет с производительностью кассы в этот момент? или кассы надо будет делать на core i7 все с ssd. Как думаете что легче грузить? 4 и более гб за раз или порциями по 20 мб? Дак чем нам мешает ограничение?
14. TODD22 19 15.03.17 07:35 Сейчас в теме
(7)
Вообщем если хотим передать кучу данных - пишем их тупо в файл на ftp - самый правильный и надежный способ.

Как показывает практика не самый надёжный способ. У меня две сети магазинов. В одной ftp проработал 2 года. Неделю назад его перезагрузили. Теперь работает очень плохо.... файлы принимает через раз. Имена файлов кривые. Обмены проходят с 4-5 попытки.
Во второй сети такие же проблемы, то имена файлов кривые, то файл обмена с 3-4 попытки на ftp закидывает.


Но и с web сервисами как оказалось то же не всё гладко. Написал сервис передаёт маленькие xml. Из за плохого интернета очень часто подвешивает платформу.
10. SinglCOOLer 217 14.03.17 11:03 Сейчас в теме
(6) Не сталкивались с такой проблемой, может у нас разная реализация, т.к. по сути дробление идет на верхнем уровне
Оставьте свое сообщение