Рассмотрим весьма распространенную, но от этого не менее неприятную ситуацию: в вашей инфраструктуре настроен кластер 1С с несколькими рабочими серверами. Вы настраиваете подключение из одной базы в другую через классическое COM-соединение (с помощью V83.COMConnector). Само подключение вроде бы проходит успешно, ошибок авторизации нет. Однако при попытке обратиться к объектам внешней базы (например, к справочникам) вы получаете системную ошибку: «Значение не является значением объектного типа (Справочники)».
При этом ситуация часто сопровождается «плавающим» поведением: если запустить код на тестовом сервере — всё работает. Если все пользователи находятся на одном рабочем сервере — всё работает. Но как только нагрузка распределяется между двумя серверами кластера, COM-соединение начинает сбоить. Проанализируем эту ситуацию детально и разберем все возможные причины и методы решения.
Давайте посмотрим на типичный кусок кода, на котором возникает сбой:
// Предполагается, что ВнешняяБаза - это успешно созданное COM-соединение
Подр_ЗУП = ВнешняяБаза.Справочники.ПодразделенияОрганизаций.ПустаяСсылка;
Если платформа выдает ошибку о том, что значение не является объектным типом, это означает только одно: переменная ВнешняяБаза в этот момент времени больше не содержит COM-объект. Как было отмечено в процессе отладки, эта переменная может внезапно содержать пустую ссылку на справочник, число, строку или тип Неопределено. Разберем по шагам, почему это происходит.
Первым делом проанализируем сам программный код. Часто причина кроется в банальной опечатке или логической ошибке внутри сложных циклов или условий. Выясним причину, почему переменная меняет тип.
ВнешняяБаза (или та, в которой хранится соединение).ВнешняяБаза = ВнешняяБаза.Справочники.ПодразделенияОрганизаций.ПустаяСсылка.Рассмотрим более глубокую архитектурную проблему. COM-объекты в 1С:Предприятие существуют исключительно в оперативной памяти того конкретного рабочего процесса (rphost), в котором они были инициализированы.
Что происходит в кластере с несколькими рабочими серверами?
ВнешняяБаза инициализирована.ВнешняяБаза становится разрушенной или пустой. Отсюда и возникает ошибка при обращении к свойству Справочники.Как исправить: Никогда не передавайте COM-объекты между клиентом и сервером. Вся работа с COM-соединением (от установки подключения до чтения данных и закрытия соединения) должна происходить в рамках одного серверного вызова. Не сохраняйте COM-объекты в реквизиты формы, параметры сеанса или временное хранилище.
Если код отрабатывает в одном серверном вызове, но проблема сохраняется (особенно при кросс-серверном взаимодействии), давайте настроим изоляцию COM-компоненты на уровне операционной системы Windows. Вынос v83.COMConnector в отдельное приложение COM+ (Component Services) решает сразу множество проблем с правами и стабильностью.
Разберем по шагам, как это сделать:
dcomcnfg).V83COM_App). Укажите тип активации — «Серверное приложение» (будет запускаться в отдельном процессе dllhost.exe).V83.COMConnector, зайдите в его свойства.Проанализируем контекст выполнения вашего кода. Если процедура подключения к внешней базе запускается из внешней обработки, расширения или через фоновое/регламентное задание, платформа 1С может неявно активировать «Безопасный режим». В этом режиме платформа искусственно ограничивает возможности работы с COM-технологиями и внешними ресурсами.
Объект соединения может создаться, метод Connect вернет успешный результат, но при попытке получить свойства внешней базы платформа заблокирует доступ. Чтобы исключить эту причину, используйте явное отключение безопасного режима перед установкой соединения (если у вас есть на это права):
УстановитьБезопасныйРежим(Ложь);
// Далее инициализируем COM-объект
ВнешняяБаза = Новый COMОбъект("V83.COMConnector");
// ... код подключения ...
Посмотрим на сетевой уровень взаимодействия. Если серверы общаются друг с другом по сети, ОС Windows может использовать протокол IPv6 по умолчанию. Компонента DCOM иногда работает с ним нестабильно, из-за чего тяжелые вызовы (например, получение метаданных Справочники) отваливаются по таймауту.
Что мы можем предпринять:
C:\Windows\System32\drivers\etc\hosts.192.168.1.10 server1c-work1
192.168.1.11 server1c-work2
Также рекомендуется оборачивать проблемные участки кода в конструкции перехвата исключений, чтобы получать более точную техническую информацию из платформы:
Попытка
Подр_ЗУП = ВнешняяБаза.Справочники.ПодразделенияОрганизаций.ПустаяСсылка;
Исключение
ТекстОшибки = ОписаниеОшибки();
ЗаписьЖурналаРегистрации("Обмен_COM", УровеньЖурналаРегистрации.Ошибка, , , ТекстОшибки);
Сообщить("Ошибка инициализации объекта: " + ТекстОшибки);
КонецПопытки;
В завершение проанализируем перспективность используемой технологии. Технология COM-соединений является устаревшей и обладает рядом непреодолимых архитектурных недостатков:
comcntr.dll на клиенте и сервере должны совпадать до последней цифры сборки. При обновлениях это часто вызывает простои.rphost.Поэтому самым надежным и современным решением вашей задачи будет отказ от COM в пользу HTTP-сервисов или OData. REST API пишется один раз, работает поверх обычного протокола HTTP/HTTPS, не зависит от разности платформ на разных серверах, отлично балансируется в кластере и позволяет легко передавать данные в формате JSON или XML.