Работа с COM-соединениями в среде 1С часто преподносит неприятные сюрпризы, особенно когда речь идет о параллельном проведении документов в двух разных системах. Ситуация, когда в базе-источнике вылетает исключение 10054, а в базе-приемнике данные успешно записываются и проводятся, является классическим примером «рассинхрона» подтверждения транзакции. В этой статье мы подробно проанализируем, почему это происходит, разберем технические причины на уровне сети и платформы, а также рассмотрим способы устранения данной проблемы.
Разберем детально механизм взаимодействия. Когда мы вызываем метод проведения документа в удаленной базе через COM-объект, цепочка событий выглядит следующим образом:
Удаленный хост принудительно разорвал существующее подключение (10054).В результате мы имеем патовое состояние: в Журнале Регистрации базы-приемника всё чисто (подключились, провели, отключились), а в базе-источнике срабатывает блок Исключение, и локальная транзакция откатывается. Проанализируем основные причины, которые могут приводить к такому поведению.
Одной из наиболее вероятных причин являются специфические баги конкретных релизов платформы 1С. Рассмотрим подробнее ситуацию с версиями 8.3.18.хххх и смежными ветками. В этих релизах наблюдались проблемы с управлением ресурсами при работе с COM-объектами в режиме толстого клиента.
Если сеанс-источник потребляет значительный объем оперативной памяти или если в коде происходит интенсивная передача тяжелых объектов через COM, операционная система может принудительно закрыть сетевой дескриптор или дочерний поток. Это часто случается именно в момент возврата управления из внешнего объекта обратно в вызывающий код 1С. Программа пытается освободить ресурсы COM, но из-за внутренней ошибки платформы делает это некорректно, что интерпретируется сетевым стеком Windows как аварийный разрыв соединения.
Часто проблема кроется в настройках операционной системы и сетевого оборудования. Проанализируем ситуацию: если проведение документа в базе-приемнике занимает значительное время (например, более 30 секунд из-за сложных расчетов в обработке ОбработкаПроведения), сетевое оборудование или брандмауэр может посчитать соединение неактивным (IDLE) и закрыть его.
Для решения этой проблемы необходимо проверить параметры Keep-Alive в реестре Windows на обоих серверах (источнике и приемнике). Разберем, какие ключи за это отвечают:
Путь в реестре: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
KeepAliveTime — определяет частоту, с которой TCP посылает пакет проверки связи. По умолчанию это может быть 2 часа. Рекомендуется уменьшить это значение до 30-60 секунд в условиях нестабильных COM-соединений.KeepAliveInterval — определяет интервал между повторными посылками проверочного пакета, если ответ не был получен.Если время выполнения транзакции в 1С превышает системные лимиты ожидания пакета подтверждения (ACK), сетевой стек разорвет связь именно в тот момент, когда приложение попытается отправить ответ после завершения записи данных.
Поскольку в описанной ситуации используется толстый клиент, взаимодействие часто опирается на механизмы DCOM. Рассмотрим, как это влияет на стабильность. В оснастке dcomcnfg (Службы компонентов) существуют настройки времени жизни вызова RPC. Если удаленный сервер долго не отвечает из-за высокой нагрузки на дисковую подсистему или CPU в момент записи документа, вызывающая сторона сбрасывает соединение по внутреннему таймауту.
Также важно учитывать лимиты на количество одновременных подключений. Если ваша обработка проводит документы в цикле очень быстро, система может не успевать корректно закрывать старые сокеты, что приводит к исчерпанию пула портов и принудительному сбросу новых соединений удаленным хостом.
Для выявления закономерности рекомендуется проанализировать длительность входящих сеансов в базе-приемнике. Посмотрим на пример данных из Журнала Регистрации:
Сеанс.Начало и время фиксации транзакции.Если стандартных логов недостаточно, придется настроить Технологический Журнал (ТЖ) на стороне источника. Нас интересуют события EXCP (исключения) и COM. Это позволит увидеть, на какой именно инструкции внутри 1С происходит обрыв и какой сетевой вызов возвращает код ошибки 10054.
Если проблему не удается решить настройкой сети или обновлением платформы, стоит рассмотреть программные методы предотвращения рассинхрона данных. Рассмотрим несколько вариантов:
Вместо прямой попытки проведения документа, разделим процесс на два этапа:
Записать(РежимЗаписиДокумента.Проведение). Это минимизирует время удержания COM-соединения в активной транзакции и снижает риск разрыва по таймауту.Если вы используете запуск полноценного приложения через V83.Application, попробуйте переключиться на V83.COMConnector. Разберем разницу:
V83.Application — запускает полноценный процесс 1С (даже без видимого окна), что требует огромного количества ресурсов и подвержено сбоям из-за инициализации интерфейсных модулей.V83.COMConnector — работает внутри процесса вызывающей программы, потребляет в разы меньше памяти и работает значительно быстрее.Пример использования COMConnector для стабильной записи:
// Инициализация соединения
Connector = Новый COMОбъект("V83.COMConnector");
Connection = Connector.Connect("Srvr='ServerName';Ref='BaseName';Usr='Login';Pwd='Password';");
Попытка
УдаленныйДокумент = Connection.Документы.РеализацияТоваровУслуг.НайтиПоНомеру(НомерДок, ДатаДок);
Если Не УдаленныйДокумент.Пустая() Тогда
ОбъектДок = УдаленныйДокумент.ПолучитьОбъект();
ОбъектДок.Записать(Connection.FixedStruct.РежимЗаписиДокумента.Проведение);
КонецЕсли;
Исключение
// Обработка ошибки 10054
ЗаписьЖурналаРегистрации("COM_Exchange", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
КонецПопытки;
Самый надежный способ — отказаться от проведения "в реальном времени" через COM. Рассмотрим схему с очередью:
Заключение: Ошибка 10054 при успешной транзакции в COM — это следствие того, что физический уровень связи (TCP/IP) обрывается раньше, чем логический уровень (COM-ответ 1С) успевает сообщить об успехе. Тщательная настройка параметров Keep-Alive, использование COMConnector вместо Application и переход к транзакционной устойчивости (проверка состояния перед повторной записью) позволят навсегда забыть об этой проблеме.