При организации взаимодействия между двумя информационными базами 1С:Предприятие, находящимися на разных физических серверах или в различных подсетях, разработчики часто сталкиваются с критической проблемой: инициализация COMConnector длится от 5 до 12 минут, а каждое последующее обращение к методам или реквизитам внешней базы происходит с огромными задержками.
При этом прямое подключение тонкого или толстого клиента 1С к удаленной базе выполняется быстро, а локальный обмен в рамках одного сервера работает мгновенно. Рассмотрим причины такого поведения системы, проанализируем варианты настройки среды исполнения и разберем наиболее эффективное архитектурное решение.
Проанализируем ситуацию с технической точки зрения. Компонент V83.COMConnector основан на технологии Microsoft DCOM (Distributed COM) и протоколе RPC (Remote Procedure Call). В отличии от стандартного клиенского подключения 1С, оптимизирующего передачу данных, COM-соединение предъявляет специфические требования к сетевой инфраструктуре и авторизации:
ПолучитьСсылку() или запись объекта через Записать() генерируют отдельные RPC-запросы. Если между подсетями есть пусть даже небольшая сетевая задержка (Latency), суммарное время серии мелких вызовов возрастает экспоненциально.Посмотрим на типичный пример кода, который при межсерверном вызове по сети вызывает сильные зависания:
// Инициализация соединения по сети
КомБаза = Новый COMОбъект("V83.COMConnector");
Соединение = КомБаза.Connect("Srvr=""192.168.2.10"";Ref=""BaseBUH"";Usr=""ExchangeUser"";Pwd=""Pass"";");
// Каждое обращение к методам ниже выполняется по 4-6 минут
ВнешняяСсылка = Соединение.Справочники.Показатели.ПолучитьСсылку(ВнешнийИД);
ПоказательКомОбъект = Соединение.Справочники.Показатели.СоздатьЭлемент();
ПоказательКомОбъект.Записать();
Для того чтобы COM-объект создавался непосредственно в процессе сервера приложений, а не загружался локально с сетевыми вызовами, используем второй параметр конструктора Новый COMОбъект, передавая в него имя сервера:
// Указываем имя сервера 1С, на котором должен создаваться процесс COM
КомОбъект = Новый COMОбъект("V83.COMConnector", "ИмяСервераПриложений");
Соединение = КомОбъект.Connect("Srvr=""Server1C"";Ref=""BaseName"";Usr=""Admin"";Pwd=""123"";");
Для корректной работы данной схемы выполним настройку приложения COM+ на сервере 1С:
v83comconnector (если его нет, создадим новое приложение COM+ и добавим компоненты comcntr.dll).Разберем шаг за шагом, как исключить сетевые тайм-ауты на уровне операционной системы, если использование COM Connector неизбежно:
C:\Windows\System32\drivers\etc\hosts и добавляем соответствия IP-адресов и сетевых имен серверов. Это исключает задержки при DNS-резолвинге.bin платформы 1С на сервере-источнике прописываем точные параметры поиска лицензий, отключив Broadcast:
[NH_TCPIP]
NH_USE_BROADCAST = Disabled
NH_TCPIP_METHOD = TCP
NH_SERVER_ADDR = 192.168.2.10
Технология COM/DCOM является устаревшей, платформозависимой (работает только в Windows) и не предназначенной для высокой нагрузки при межсетевом обмене. Практика показывает, что наиболее эффективное решение проблемы медленного COM Connector — полный отказ от него в пользу HTTP-сервисов 1С.
Преимущества HTTP-сервисов по сравнению с COM Connector:
Проанализируем пример реализации получения данных через HTTP-сервис вместо вызова COM Connector.
На стороне базы-приемника (куда раньше подключались по COM) создаем HTTP-сервис с шаблоном URL /get_data/* и методом GET:
// Функция-обработчик HTTP-запроса на стороне базы-источника данных
Функция ПолучитьДанныеGET(Запрос)
Ответ = Новый HTTPСервисОтвет(200);
Ответ.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
// Формируем структуру с данными
ДанныеСтруктура = Новый Структура;
ДанныеСтруктура.Вставить("Идентификатор", "000000001");
ДанныеСтруктура.Вставить("Наименование", "Показатель 1");
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, ДанныеСтруктура);
Ответ.УстановитьТелоИзСтроки(ЗаписьJSON.Закрыть());
Возврат Ответ;
КонецФункции
На стороне отправляющей базы вызов выполняем с помощью объектов HTTPСоединение и HTTPЗапрос:
// Вызов HTTP-сервиса вместо установки COM-соединения
Сервер = "192.168.2.10";
Ресурс = "/BaseBUH/hs/Exchange/get_data/";
ЗащищенноеСоединение = Неопределено;
Соединение = Новый HTTPСоединение(Сервер, 80, "WebUser", "WebPassword", , , ЗащищенноеСоединение);
Запрос = Новый HTTPЗапрос(Ресурс);
Ответ = Соединение.Получить(Запрос);
Если Ответ.КодСостояния = 200 Тогда
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(Ответ.ПолучитьТелоКакСтроку());
Результат = ПрочитатьJSON(ЧтениеJSON);
Сообщить("Получены данные: " + Результат.Наименование);
КонецЕсли;
Перевод обмена с COM Connector на HTTP-сервисы ускоряет выполнение процедур интеграции в десятки раз и полностью устраняет проблемы с зависанием сетевых вызовов.