В этой статье я расскажу о многих особенностях взаимодействия между базами 1С по COM технологии, накопленных за годы развития и использования интеграционного коммерческого продукта 2iS:Интеграция нашей компании 2iS.
Термины
ОС – операционная система
COM-клиент – процесс(поток) ОС, запросивший создание COM-объекта
COM-сервер – COM-объект, созданный по запросу клиента
Com-соединитель – COM-объект V8X.ComСonnector для создания внешних соединений с базами 1С
Automation-сервер – он же OLE-сервер, COM-объект V8X.Application для создания приложений 1С
Издание платформы – подстрока до 2-й точки версии платформы (например 8.2, 8.3)
Сборка платформы – полная строка версии платформы (например 8.2.19.130, 8.2.16.352)
Подключение внешнего соединения
Рассмотрим алгоритм подключения внешнего соединения в деталях
-
Создание COM-объекта Com-соединитель (Имя класса - V8X.ComConnector). Варианты:
-
Внутрипроцессное (inproc)
-
Должен быть зарегистрирован класс V8X.ComConnector той же разрядности, что и COM-клиент
-
Если издание платформы COM-клиента совпадает с изданием платформы COM-сервера, то также требуется равенство сборки платформы COM-клиента и COM-сервера.
-
Он регистрируется при установке платформы с опцией «Внешнее соединение». В любой момент его можно зарегистрировать командой «Regsvr32 comcntr.dll» в каталоге исполняемых файлов платформы.
-
COM-объект создается в памяти COM-клиента
-
Затраты на создание примерно – 0.01(первое)/0.001(второе) cек
-
Пример
КомСоединитель = Новый COMОбъект(“V83.ComConnector”);
ВнешнееСоединение = КомСоединитель.Connect(СтрокаСоединения); -
Внепроцессное локальное (local)
-
Должен быть зарегистрирован класс V8X.ComConnector любой разрядности и сборки платформы. Необходимо настроить через dcomcnfg.exe COM+ приложение с активацией «серверное приложение»/«Server apllication». Подробнее рассмотрено далее.
-
COM-объект создается в памяти служебного хост-процесса (dllhost.exe) на компьютере COM-клиента
-
Затраты на создание примерно – 0.06(первое)/0.03(второе) сек
-
Пример
КомСоединитель = Новый COMОбъект(“V83.ComConnector”);
ВнешнееСоединение = КомСоединитель.Connect(СтрокаСоединения); -
Внепроцессное нелокальное (DCOM)
-
На нелокальном компьютере должен быть зарегистрирован класс V8X.ComConnector любой разрядности и сборки платформы. Необходимо настроить на нелокальном компьютере через dcomcnfg.exe COM+ приложение с активацией «Cерверное приложение»/«Server apllication». Подробнее рассмотрено далее.
-
Необходимо настроить на нелокальном компьютере роль «Сервер приложений»/«Application server» и включить нелокальный доступ COM+, выбрав опцию «Сетевой доступ к COM+»/”COM+ network access”. Подробнее рассмотрено далее.
-
COM-объект создается в памяти служебного хост-процесса (dllhost.exe) на другом компьютере
-
Затраты на создание примерно
-
Экспериментальные данные
Задержка канала, мс |
Длительность создания COM-объекта, мс |
0 |
60 |
30 |
700 |
80 |
2000 |
170 |
4000 |
На графике видно, что длительность создания этого COM-объекта прямо пропорциональна задержке канала и коэффициент пропорциональности составляет примерно 24. Можно предположить, что при создании этого COM-объекта происходит 24 вызова через канал.
-
Пример
КомСоединитель = Новый COMОбъект(“V83.ComConnector”, ИмяКомпьютера);
ВнешнееСоединение = КомСоединитель.Connect(СтрокаСоединения); -
Выполнение метода Connect (создание внешнего соединения)
-
Создание сеанса – 1 сек
-
Инициализация сеанса – [0;?] сек
-
ПередНачаломРаботыСистемы (только для Automation-сервера)
-
ПриНачалеРаботыСистемы
-
Инициализация параметров сеанса
-
Подгрузка нужных метаданных
Затраты на COM-вызовы
Каждый раз, когда мы обращаемся во встроенном языке к свойству или методу COM-объекта (выполняем COM-вызов), происходит ряд дополнительных действий по сравнению с обращением к родному объекту встроенного языка. Если COM-сервер находится в другом локальном процессе, то при этом еще сначала выполняется перенос всех параметров из COM-клиента в COM-сервер и в конце выполняется обратный перенос параметров в COM-клиент. Для такого переноса информация естественно должна быть сериализована на стороне отправителя и затем десериализована на стороне получателя, что в совокупности с некоторыми другими действиями получило название маршалинга и демаршалинга. В нелокальном режиме (DCOM) такой перенос будет еще тратить время на сетевые коммуникации и при первом обращении к новому COM-объекту на передачу его «скелета», и поэтому задержка канала будет играть решающую роль (Подробнее о COM вызовах, DCOM в википедии, Технический обзор DCOM,)
Соотношение затрат на вызов по типам расположения COM-сервера
-
Минимальные для внутрипроцессного Com-сервера
-
Средние для локального внепроцессного Com-сервера
-
От средних до больших для нелокального внепроцессного Cоm-сервера в зависимости от качества канала связи
Минимизация количества COM-вызовов
-
Создаем базовую внешнюю обработку с набором общих методов для приема вызовов от COM-клиента на стороне COM-сервера
-
Теперь нам не нужно изменять конфигурацию базы COM-сервера, чтобы использовать там сложный функционал.
-
В нашем продукте мы назвали ее «Сервисный процессор». На ее передачу и инициализацию уходит около 1 сек
-
Проектируем взаимодействие с COM-сервером по принципу "минимум COM-вызовов”, т.е. готовим все нужное на стороне COM-клиента и передаем в качестве параметров одного большого вызова»
-
Создаем встроенную обработку для выполнения такого вызова в COM-клиенте
-
Передача агрегатных объектов
-
Сериализуем все входные параметры на стороне COM-клиента
-
Десериализуем все входные параметры на стороне COM-сервера
-
Сериализуем все выходные параметры на стороне COM-сервера
-
Десериализуем все выходные параметры на стороне COM-клиента
-
В нашем продукте мы назвали ее «Выполнение сервиса инфобазы»
-
Для многократных COM-вызовов предусматриваем регулируемую частоту
-
Например, информационные вызовы могут выполняться с изменяемой частотой
Обратная связь
При использовании принципа «минимум COM-вызовов» значительную часть времени код будет выполняться в чужом контексте, что серьезно усиливает некоторые неудобства COM-вызовов:
-
Нельзя прервать поток COM-Клиента и его соединение с сервером приложений 1С, пока не завершится вызов COM-сервера
-
У COM-Клиента нет информации о прогрессе выполнения вызова в COM-сервере
Для борьбы с этими неудобствами можно организовать обратную связь от COM-сервера к COM-клиенту, передав COM-Серверу ссылку на общий модуль COM-клиента и периодически вызывая через нее COM-клиент. Нужно отметить, что есть ошибки платформы (https://partners.v8.1c.ru/forum/t/1382465/m/1382465 ), проявляющиеся при создании ссылок на один общий модуль более чем в одном COM-севере сеанса. Поэтому пока лучше очищать ссылки на общий модуль во всех удерживаемых COM-серверах перед помещением в новый. В обратных вызовах можно передавать:
-
информацию о прогрессе выполнения
-
накопленные сообщения пользователю (получать функцией ПолучитьСообщенияПользователю(Истина))
Схема принципа “минимум COM-вызовов”
Такая схема дружественна к большим задержкам каналов связи. Поэтому она во многом похожа на вызов веб-сервиса. А следовательно используя ее для COM взаимодействия, вы значительно снижаете затраты на возможные переходы между COM и веб-сервисом в обоих направлениях.
Отладка
При использовании принципа «минимум COM-вызовов» облегчить отладку выполнения кода на COM-сервере можно, сделав опциональное модальное окно подключения к базе в COM-клиенте. В этом окне должны быть возможности задания одноразовых параметров подключения, выполнения вспомогательных функций и просмотра информации о подключенном сеансе. Ниже в качестве примера показано такое окно из нашего продукта
Чтобы включить возможность отладки внешних соединений, в подкаталоге conf нужно создать файл comcntrcfg.xml с соответствующим содержимым. В окне подключения можно сделать кнопку/флажок для программного создания такого файла. Однако много версий платформы содержат ошибку, из-за которой предметы отладки внешних соединений не видны в отладчике даже с этим корректно настроенным файлом. На платформе 8.3 эти проблемы вроде бы решены.
Пример файла comcntrcfg.xml:
<config xmlns="http://v8.1c.ru/v8/comcntrcfg">
<debugconfig debug="true" debuggerURL="tcp://localhost:1560"/>
</config>
Также нельзя забывать о необходимости запускать конфигуратор для отладки с той же (до регистра букв) строкой соединения, что и предмет отладки. Поэтому в этом диалоге нужно сделать кнопку для запуска конфигуратора COM-сервера с правильной строкой соединения.
В какой-то мере обойти проблему невидимости предмета отладки внешнего соединения и ряд других неудобств можно путем однократного выполнения кода на толстом клиенте с заменой режима «Внешнее соединение» на «Automation-сервер» (приложение), т.е. используя COM класс V8X.Application и включенную видимость. Поэтому в окне подключения нужны параметры для выбора режима подключения.
После создания подключения на стороне COM-клиента обычно требуется подключение отладчика базы COM-сервера и установка там точки останова в нужном месте. Поэтому в окне подключения нужно расположить кнопку подключения отладчика/конфигуратора COM-сервера. Если COM-сервер запущен в режиме видимого приложения, то для подключения отладчика можно воспользоваться асинхронным вызовом исключения в нем. Из диалога с ошибкой в приложении COM-сервера через кнопку «Конфигуратор» можно будет открыть конфигуратор и в большинстве случаев сразу подключить отладчик. Если подключение отладчика таким способом недоступно, то оператору поможет отображение информации о сеансе (его номера) в базе COM-сервера. Также нужна кнопка открытия в открытом отладчике файла внешней обработки, которая будет выполняться в нем.
Управление COM классами и COM+ приложениями 1С
Управление COM классами
-
Внешнее соединение (V8X.ComConnector)
-
Регистрация: Regsvr32 comcntr.dll
-
Отмена регистрации: Regsvr32 comcntr.dll /u
-
Automation-сервер (V8X.Application)
-
Регистрация - 1cv8.exe /regserver
-
Отмена регистрации - 1cv8.exe /unregserver
Управление COM+ приложениями
Осуществляется через оснастку dcomcnfg.exe. Для регистрации 1С в качестве COM+ приложения необходимо открыть оснастку "dcomcnfg". В ней в ветке "Службы компонентов"-"Компьютеры"-"Мой компьютер"-"Приложения COM+"(COM+ Applications) необходимо добавить новое приложение (application). При добавлении можно указать любое имя. Далее необходимо указать пользователя, от имени которого будет работать COM+ приложение, на закладке Идентификация (Identity). Также нужно задать доступ к приложению для всех пользователей путем добавления, если отсутствует, роли с любым именем в ветке Роли (Roles), и добавления в ее ветку Пользователи (Users) пользователя Все (Everyone). После добавления приложения необходимо создать новую компоненту. Для этого в ветке "Компоненты" созданного приложения необходимо выбрать пункт меню "Создать"-"Компонент". При создании выбрать импорт уже зарегистрированных компонентов и найдите в списке (желательно 64-битную) компоненту 1С (V8x.COMConnector.1).
Далее можно изменить тип активации (внутрипроцессный/внепроцессный) на закладке Активация/Activation.
В нашем продукте имеется инструмент «Управление COM классами 1С» для просмотра/регистрации/изменения всех COM классов и COM+ приложений 1С на указанном компьютере:
Настройка DCOM-сервера
Для Windows 2008 Server нужно добавить роль «Сервер приложений» (Application server). Для этого необходимо открыть панель управления компьютером, щелкнуть правой кнопкой мыши в ветки "Роли" и выбрать пункт меню "Добавить роль".
Появится око в котором необходимо выбрать роль "Сервер приложений"/"Application server". На этапе выбора ролей сервера приложений необходимо указать пункт "Сетевой доступ к COM+"/"COM+ network access". Если это не сделать, то при попытке создания COM-объекта вы будете получать ошибку "Ошибка при вызове конструктора (COMОбъект): The component or application containing the component has been disabled".
Проблемы
-
Высокие затраты на подключение/инициализацию
-
Удержание com-серверов – эффективное средство борьбы
-
Временное хранилище. Производитель не рекомендует, но деваться больше некуда. http://infostart.ru/public/331683/
-
Повторное использование возвращаемых значений. Очищаются каждые 20 мин
-
Разные сборки платформы клиента и сервера при одинаковом издании платформы
-
Для обхода для каждой отличной от COM-клиента сборки платформы назначаем и настраиваем DCOM сервер
-
Отсутствие информации о типах вложенных в COM-объекты объектов 1С (вместо типа объекта 1С везде получаем тип «COMОбъект») и отсутствие контекстной подсказки по ним
-
Для обхода применяем принцип «минимум COM-вызовов»
-
При передаче исключения из COM-сервера оно принимает краткую форму из-за ошибки платформы
-
Для обхода оборачиваем каждый вызов на стороне COM-сервера в попытку и в исключении перевызываем исключение с полным описанием ошибки
-
При создании COM-объекта ошибка “Версия компоненты 'comcntr' (8.X.XX.XXX) отличается от версии корневого модуля 'core82' (8.X.YY.YYY)”
-
Для обхода создаем COM+ приложение с внепроцессной активацией. Тогда COM-сервер будет создаваться в отдельном процессе и совпадения версий этих модулей не потребуется.
-
Медленные каналы (большие задержки)
-
Каждой подсети за отдельным медленным каналом назначаем и настраиваем свой DCOM сервер и при обращении к базам за этим каналом COM-серверы создаем на этом компьютере, минимизируя количество и объемы вызовов Com-клиент<->Com-сервер
-
Кешируем (повторно используем) COM-серверы
-
Невозможно разорвать соединение рабочего процесса, в котором ожидается завершение вызова COM-сервера
-
Для обхода можно использовать создание COM-объектов в выделенных хост-процессах, настроив соответствующим образом COM+ приложение, и регистрировать идентификаторы этих процессов в привязке к сеансам COM-клиентов. Тогда при необходимости завершить серверное соединение такого сеанса можно сначала убить процесс COM-сервера, а потом и сам сеанс.
-
При обращении к COM-объекту может возникать ошибка «Неизвестная ошибка». Возможные причины:
-
Com-сервер перестал существовать. Возможные причины:
-
Переполнение стека
-
Невосстановимая ошибка
-
Хост-процесс завершился
-
Потеря связи с нелокальным COM-сервером
-
Совпадение имен свойств и методов без параметров объекта создает неоднозначность обращения к ним через COM
-
Например, если у справочника есть реквизит ПолноеНаименование, то из-за наличия метода ПолноеНаименование() обращение к реквизиту ПолноеНаименование через COM может привести к вызову метода ПолноеНаименование()
-
Для обхода используем принцип “минимум COM-вызовов”
Com-технология VS веб-сервисы в локальной сети
Недостатки
-
Рассмотренные выше сложности с взаимодействием разных сборок платформы 1C, требующие для своего решения сервисный механизм
-
Высокие затраты на подключение/инициализацию, поэтому при отсутствии кеширования неэффективно для частых мелких вызовов
-
Привязка к семейству операционных систем (платформе) Windows
Преимущества
-
Отсутствие необходимости изменять конфигурацию баз, к которым подключаемся
-
Широкая функциональность
-
Проще отладка
-
Не требуется разворачивать и поддерживать веб-сервер
Захват клиентских лицензий
В большинстве случаев всем клиентским приложениям, частным случаем которого являются Automation-сервер и с оговорками является внешнее соединение, в одном сеансе ОС требуется всего лишь одна на всех лицензия. Однако если клиентскому приложению не удалось получить аппаратную лицензию (от локального HASP или сетевого HASP) и программную лицензию (платформы или базовой конфигурации), то предпринимается попытка получить отдельную лицензию с сервера 1С:Предприятия. Сервер 1С:Предприятия может выдать лицензию только, если в свойствах базы разрешена выдача лицензий сервером 1С:Предприятия. В таком случае каждое клиентское приложение и внешнее соединение может захватывать свою собственную лицензию.
Заключение
Если вы хотите подробнее узнать об описанных особенностях, вы можете бесплатно скачать конфигурацию и демонстрационную базу продукта, для чего необходимо оформить предварительный заказ на Инфостарте на продукт 2iS:Интеграция. Несмотря на наличие в конфигурации защищенного модуля, 99% программного кода конфигурации открыто, то есть Вы можете изучить реализацию описанных приемов.
Начать дискуссию