После миграции информационных баз 1С с сервера под управлением Windows на Linux многие пользователи сталкиваются с проблемой невозможности использования COM-соединения. Это происходит потому, что технология COM (Component Object Model) является специфичной для операционных систем семейства Microsoft Windows. В среде Linux такое подключение становится невозможным, что требует пересмотра архитектуры обмена данными между базами 1С. В этом тексте мы рассмотрим различные альтернативные методы для организации обмена данными и получения отчетов, которые будут работать в кроссплатформенной среде.
Переход на новые технологии — это не только вынужденная мера, но и возможность повысить надежность, масштабируемость и безопасность ваших решений. Давайте вместе разберем, какие инструменты предлагает платформа 1С для интеграции в условиях Linux-сервера.
Одним из наиболее современных и рекомендуемых способов для интеграции между базами 1С и внешними системами являются HTTP-сервисы и Web-сервисы. Эти механизмы позволяют нам создавать гибкие и производительные программные интерфейсы.
Мы можем создать на стороне одной базы 1С программные интерфейсы (сервисы), к которым будут обращаться другие системы или другая база 1С через протокол HTTP. Данные при этом обычно передаются в структурированных форматах, таких как XML или JSON. База-источник отправляет HTTP-запрос, а база-приемник обрабатывает его и возвращает необходимые данные.
Для использования HTTP/Web-сервисов нам необходимо опубликовать информационную базу на веб-сервере, таком как Apache или Nginx. В конфигурации базы-источника мы создаем объект Web-сервис или HTTP-сервис, а в базе-приемнике используем WS-ссылки или методы объекта HTTPСоединение для отправки запросов. Операции сервиса описываются функциями встроенного языка 1С и должны возвращать какое-либо значение. HTTP-сервисы часто используют стандартные HTTP-методы (GET, POST, PUT, DELETE) для различных операций с данными.
Пример реализации для формирования отчета по данным из другой базы:
Представим, что нам нужно получить данные для отчета из Базы Б, находясь в Базе А. Мы можем сделать так:
// --- Код в конфигурации Базы Б (публикуется как HTTP-сервис) ---
// Создаем HTTP-сервис "ОтчетныйСервис" с URL-шаблоном "/ПолучитьДанныеДляОтчета"
// В обработчике метода POST этого сервиса:
Функция ПолучитьДанныеДляОтчетаPOST(Запрос)
// Инициализируем объект ответа
Ответ = Новый HTTPСервисОтвет(200);
Попытка
// Получаем тело запроса как строку, ожидаем JSON с параметрами СКД
ТекстЗапроса = Запрос.ПолучитьТелоКакСтроку();
ПараметрыЗапроса = JSONДекодировать(ТекстЗапроса);
// --- Логика формирования данных в Базе Б ---
// Предполагаем, что ПараметрыЗапроса содержит, например,
// схему СКД (сериализованную) и значения параметров отчета.
// Мы можем также подменить текущего пользователя для корректной работы RLS.
//
// Если необходимо соблюдение RLS, сначала сохраним текущего пользователя:
// ТекущийПользователь = ПараметрыСеанса.ТекущийПользователь;
// ПараметрыСеанса.ТекущийПользователь = Справочники.Пользователи.НайтиПоКоду("ПользовательДляОтчетов");
//
// Создаем и настраиваем отчет на основе полученных параметров
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
КомпоновщикМакета.Инициализировать(Новый ИсточникДоступныхПолейКомпоновкиДанных(ПараметрыЗапроса.СхемаСКД));
// Устанавливаем параметры и отборы, полученные из запроса
НастройкиОтчета = КомпоновщикМакета.Настройки; // Или десериализуем настройки из ПараметрыЗапроса
// ... Пример установки параметра ...
// НастройкиОтчета.ПараметрыДанных.УстановитьЗначениеПараметра("ДатаНачала", ПараметрыЗапроса.ДатаНачала);
МакетКомпоновки = КомпоновщикМакета.Выполнить();
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, Новый ВнешниеНаборыДанных);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
РезультатОтчета = Новый ТаблицаЗначений;
ПроцессорВывода.УстановитьОбъект(РезультатОтчета);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
// Если меняли пользователя для RLS, восстановим его:
// ПараметрыСеанса.ТекущийПользователь = ТекущийПользователь;
//
// Сериализуем полученную таблицу значений в JSON для отправки обратно
СтрокаJSONРезультата = JSONСериализовать(РезультатОтчета);
Ответ.УстановитьТелоИзСтроки(СтрокаJSONРезультата, "application/json", КодировкаТекста.UTF8);
Исключение
Ответ.КодСостояния = 500;
Ответ.УстановитьТелоИзСтроки("Ошибка при формировании отчета: " + ОписаниеОшибки(), "text/plain", КодировкаТекста.UTF8);
КонецПопытки;
Возврат Ответ;
КонецФункции
// --- Код в конфигурации Базы А (откуда делаем запрос) ---
Функция ПолучитьДанныеИзБазыБ(ПараметрыДляОтчета)
URLСервиса = "http://ваш.сервер.1c/имя_публикации_базыБ/hs/ОтчетныйСервис/ПолучитьДанныеДляОтчета";
// Сериализуем параметры для Базы Б в JSON
СтрокаJSONПараметров = JSONСериализовать(ПараметрыДляОтчета);
HTTPЗапрос = Новый HTTPЗапрос(URLСервиса);
HTTPЗапрос.УстановитьЗаголовок("Content-Type", "application/json;charset=utf-8");
HTTPЗапрос.УстановитьТелоИзСтроки(СтрокаJSONПараметров, "utf-8");
// Создаем HTTPСоединение (указываем данные для аутентификации, если сервис защищен)
Соединение = Новый HTTPСоединение("ваш.сервер.1c", 80, "пользователь_сервиса", "пароль_сервиса", , Истина);
Попытка
Ответ = Соединение.Отправить(HTTPЗапрос);
Если Ответ.КодСостояния = 200 Тогда
СтрокаJSONРезультата = Ответ.ПолучитьТелоКакСтроку();
// Десериализуем JSON в ТаблицуЗначений
ТаблицаДанных = JSONДекодировать(СтрокаJSONРезультата);
Возврат ТаблицаДанных;
Иначе
Сообщить("Ошибка запроса к сервису: " + Ответ.КодСостояния + " - " + Ответ.ПолучитьТелоКакСтроку());
Возврат Неопределено;
КонецЕсли;
Исключение
Сообщить("Исключение при выполнении HTTP-запроса: " + ОписаниеОшибки());
Возврат Неопределено;
КонецПопытки;
КонецФункции
// Пример вызова в Базе А:
// ПараметрыОтчета = Новый Структура("СхемаСКД, ДатаНачала", ПолучитьСхемуСКДДляОтчета(), НачалоДня(ТекущаяДата()));
// РезультатОтчетаИзБазыБ = ПолучитьДанныеИзБазыБ(ПараметрыОтчета);
// Если РезультатОтчетаИзБазыБ <> Неопределено Тогда
// // Дальше работаем с РезультатОтчетаИзБазыБ как с обычной ТаблицейЗначений
// КонецЕсли;
Мы также можем создавать кэширующие таблицы для запросов, чтобы не запрашивать одни и те же данные многократно. Если кэш протух, мы делаем новый запрос и обновляем данные, что значительно снижает нагрузку при частом формировании отчетов.
OData — это открытый веб-протокол для обмена данными, который активно поддерживается платформой 1С. Он предоставляет стандартизированный способ доступа к данным информационной базы через HTTP-запросы.
С помощью OData мы можем получать, изменять и удалять данные из базы 1С. Протокол позволяет работать как с метаданными, так и непосредственно с объектами конфигурации: документами, справочниками, регистрами, константами. Мы можем применять фильтры, создавать и удалять элементы, проводить и отменять проведение документов, запускать бизнес-процессы и получать остатки/обороты по регистрам.
Ответы от OData-сервиса могут быть получены в форматах Atom/XML или JSON, что делает его удобным для интеграции с различными системами.
Важно понимать, что OData не всегда оптимален для очень сложных запросов с большим количеством фильтров и сложной логикой. В таких случаях создание собственного HTTP-сервиса, как мы рассмотрели выше, может быть более эффективным, поскольку он позволяет полностью контролировать логику обработки данных на стороне сервера. Мы можем, например, предварительно допилить базу напильником, сложить сложные пути получения данных в виде готовых регистров, и уже их получать через OData или простые HTTP-сервисы, повесив формирование этих регистров на фоновые задания.
Для работы с OData требуется публикация информационной базы на веб-сервере с обязательной опцией "Публиковать стандартный интерфейс OData".
Представим, что мы хотим получить список контрагентов из другой базы 1С.
// --- Код в базе-источнике (делает запрос к OData другой базы) ---
// URL к стандартному OData-сервису 1С: http://<сервер>/<имя_публикации>/odata/standard.odata/
URL_OData = "http://ваш.сервер.1c/имя_публикации_базыБ/odata/standard.odata/";
// Для примера запросим контрагентов с определенным именем
// В запросе можно использовать фильтры, выбор полей, сортировку и т.д.
// Полный список возможностей OData-запросов доступен в документации 1С.
ПутьРесурса = "Catalog_Контрагенты?$filter=Description eq 'МойКонтрагент'&$select=Ref_Key,Description,ИНН";
HTTPСоединение = Новый HTTPСоединение("ваш.сервер.1c", 80, "пользователь_OData", "пароль_OData", , Истина);
HTTPЗапрос = Новый HTTPЗапрос(ПутьРесурса);
// Указываем, что хотим получить ответ в формате JSON
HTTPЗапрос.Заголовки.Вставить("Accept", "application/json;odata=light");
Попытка
Ответ = HTTPСоединение.Отправить(HTTPЗапрос);
Если Ответ.КодСостояния = 200 Тогда
СтрокаJSON = Ответ.ПолучитьТелоКакСтроку();
// Десериализуем полученный JSON
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(СтрокаJSON);
ОбъектJSON = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
// ОбъектJSON.value содержит массив элементов
Если ОбъектJSON.Свойство("value") Тогда
Для Каждого Контрагент Из ОбъектJSON.value Цикл
Сообщить("ИНН: " + Контрагент.ИНН + ", Наименование: " + Контрагент.Description);
КонецЦикла;
КонецЕсли;
Иначе
Сообщить("Ошибка OData-запроса: " + Ответ.КодСостояния + " " + Ответ.Статус);
Сообщить("Тело ответа: " + Ответ.ПолучитьТелоКакСтроку());
КонецЕсли;
Исключение
Сообщить("Исключение при работе с OData: " + ОписаниеОшибки());
КонецПопытки;
Несмотря на наличие более современных и гибких методов, файловый обмен по-прежнему остается актуальным и простым способом для определенных сценариев, особенно если нам не требуется "живое" получение данных.
Мы организуем обмен данными посредством выгрузки и последующей загрузки файлов (часто в формате XML) в общий каталог. Этот каталог должен быть доступен обеим базам, участвующим в обмене.
При использовании файлового обмена на Linux-сервере нам критически важно правильно настроить монтирование сетевых ресурсов (например, SMB-шар, если файлы находятся на Windows-сервере или другой Linux-машине) и предоставить необходимые права доступа. Эти права должны быть у пользователя, от имени которого работает сервер 1С. Для монтирования сетевых ресурсов часто используются утилиты cifs-utils и настройки в файле /etc/fstab. Это гарантирует, что 1С-сервер сможет читать и записывать файлы в указанном сетевом каталоге.
Платформа 1С предоставляет встроенные средства для работы с XML-файлами. Мы можем использовать стандартные объекты для чтения и записи XML, а также готовые обработки, например, ВыгрузкаЗагрузкаДанныхXML83.
Для сценариев, где мы не можем или не хотим изменять конфигурацию базы-приемника (например, в случае с клиентскими базами на поддержке или базовыми версиями), существует подход, который имитирует часть функционала COM-соединения через запуск внешних обработок.
Мы разрабатываем внешнюю обработку, которая содержит всю необходимую логику для сбора данных, выполнения проверок или формирования отчетов. Затем эту обработку мы можем запустить в целевой базе, а результат её работы получить или сохранить.
Предположим, у нас есть внешняя обработка ПроверочныйОтчет.epf, которая должна проверять паспортные данные сотрудников в целевой базе и возвращать список проблем.
// --- Код в внешней обработке (ПроверочныйОтчет.epf) ---
// Эта обработка будет загружаться и выполняться в целевой базе
Процедура ВыполнитьПроверкуИВернутьРезультат(ПараметрыЗапуска, РезультатПроверки) Экспорт
// Инициализируем выходной параметр для сбора ошибок
РезультатПроверки.Колонки.Добавить("ТипПроблемы");
РезультатПроверки.Колонки.Добавить("Описание");
РезультатПроверки.Колонки.Добавить("Сотрудник");
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| ФизическиеЛицаСрезПоследних.Ссылка КАК ФизЛицо,
| ФизическиеЛицаСрезПоследних.ДатаРождения КАК ДатаРождения,
| ДанныеДокументовУдостоверяющихЛичность.ВидДокумента,
| ДанныеДокументовУдостоверяющихЛичность.Серия,
| ДанныеДокументовУдостоверяющихЛичность.Номер,
| ДанныеДокументовУдостоверяющихЛичность.ДатаВыдачи,
| ДанныеДокументовУдостоверяющихЛичность.ДатаОкончанияСрокаДействия
|ИЗ
| РегистрСведений.ФизическиеЛица.СрезПоследних КАК ФизическиеЛицаСрезПоследних
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ДанныеДокументовУдостоверяющихЛичность КАК ДанныеДокументовУдостоверяющихЛичность
| ПО ФизическиеЛицаСрезПоследних.Ссылка = ДанныеДокументовУдостоверяющихЛичность.ФизическоеЛицо";
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Если Выборка.ВидДокумента.Наименование = "Паспорт гражданина РФ" Тогда
// Проверка на 20/45 лет
Если Год(Выборка.ДатаРождения) + 20 = Год(ТекущаяДата()) И Месяц(Выборка.ДатаРождения) = Месяц(ТекущаяДата()) И День(Выборка.ДатаРождения) < День(ТекущаяДата()) Тогда
Если Выборка.ДатаОкончанияСрокаДействия = '00010101' Тогда // Примерная проверка на отсутствие нового паспорта
НоваяСтрока = РезультатПроверки.Добавить();
НоваяСтрока.ТипПроблемы = "Истечение срока паспорта (20 лет)";
НоваяСтрока.Описание = "Паспорт подлежит замене по достижении 20 лет";
НоваяСтрока.Сотрудник = Выборка.ФизЛицо;
КонецЕсли;
ИначеЕсли Год(Выборка.ДатаРождения) + 45 = Год(ТекущаяДата()) И Месяц(Выборка.ДатаРождения) = Месяц(ТекущаяДата()) И День(Выборка.ДатаРождения) < День(ТекущаяДата()) Тогда
Если Выборка.ДатаОкончанияСрокаДействия = '00010101' Тогда
НоваяСтрока = РезультатПроверки.Добавить();
НоваяСтрока.ТипПроблемы = "Истечение срока паспорта (45 лет)";
НоваяСтрока.Описание = "Паспорт подлежит замене по достижении 45 лет";
НоваяСтрока.Сотрудник = Выборка.ФизЛицо;
КонецЕсли;
КонецЕсли;
// Дополнительные проверки, например, через HTTP-сервис к базе ФНС/МВД
// Здесь мы могли бы вызвать внешний HTTP-сервис для проверки актуальности
// данных паспорта, передав Серию и Номер.
// Если Не ПроверитьАктуальностьПаспортаВнешнимСервисом(Выборка.Серия, Выборка.Номер) Тогда
// НоваяСтрока = РезультатПроверки.Добавить();
// НоваяСтрока.ТипПроблемы = "Неактуальные паспортные данные";
// НоваяСтрока.Описание = "Паспортные данные не подтверждены внешним сервисом";
// НоваяСтрока.Сотрудник = Выборка.ФизЛицо;
// КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// --- Гипотетический код запуска внешней обработки ---
// (Этот код выполняется, например, в центральной базе или во внешнем приложении)
// Для каждой целевой базы (База_Клиента_1, База_Клиента_2 и т.д.)
// 1. Открываем сессию 1С к целевой базе (например, через запуск тонкого клиента с параметрами)
// 2. Программно загружаем внешнюю обработку
// ОбработкаОбъект = ВнешниеОбработки.Создать("ПутьКОбработке\ПроверочныйОтчет.epf");
// 3. Создаем ТаблицуЗначений для получения результата
// ТЗРезультат = Новый ТаблицаЗначений();
// 4. Вызываем экспортируемую процедуру
// ОбработкаОбъект.ВыполнитьПроверкуИВернутьРезультат(Новый Структура(), ТЗРезультат);
// 5. Обрабатываем ТЗРезультат (например, сохраняем в центральную базу или отправляем по почте)
// 6. Закрываем сессию к целевой базе
// Или, как регламентное задание (если целевая база на управляемых формах):
// 1. В конфигурации целевой базы (или расширении) создаем регламентное задание
// 2. В коде регламентного задания используем типовой механизм
// ДополнительныеОтчетыИОбработки.ВыполнитьКомандуВнешнейОбработки(
// "ИмяОбработкиВБазе", "ИмяКоманды", Неопределено, "КлючНазначения", "ОписаниеВыполнения");
// Или программно загружаем и вызываем метод:
// МенеджерДопОбработок = Справочники.ДополнительныеОтчетыИОбработки.ПолучитьМенеджер();
// Параметры = Новый Структура();
// Результат = МенеджерДопОбработок.ВыполнитьМетодВнешнейОбработки("ИмяОбработки", "ВыполнитьПроверкуИВернутьРезультат", Параметры);
// // Результат можно сохранить в регистр сведений или отправить по почте
Технология внешних компонент Native API является наиболее низкоуровневым и нативным способом расширения функционала 1С, поддерживаемым в Linux.
Мы можем создавать программы на языках программирования, таких как C++, которые динамически подключаются к 1С. Эти компоненты позволяют нам расширять возможности платформы, например, для взаимодействия со специфическим внешним оборудованием или реализации очень сложной, высокопроизводительной логики, которую трудно реализовать на встроенном языке 1С.
Компоненты, созданные по Native API, поддерживаются как в Windows, так и в Linux, и могут использоваться в различных клиентах 1С (толстый, тонкий, веб) и на сервере приложений.
Для создания таких компонент нам необходимы глубокие знания C++ и строгое следование документации 1С по Native API. Это, как правило, наиболее трудоемкий и дорогостоящий вариант, который редко выбирается для простой замены COM-соединения между базами, если есть более простые HTTP-сервисы.
EnterpriseData — это универсальный механизм для интеграции программных продуктов на платформе "1С:Предприятие" и со сторонними системами. Он основан на обмене XML-файлами со строго определенной структурой.
EnterpriseData позволяет обмениваться данными между различными конфигурациями 1С, а также с любыми другими программными платформами, которые поддерживают работу с XML.
Обмен может осуществляться различными способами: через веб-сервисы, файловый обмен (через общий каталог, FTP) или электронную почту. Данные часто передаются в сжатом виде (ZIP), что способствует сокращению трафика.
Этот формат особенно хорошо подходит для несложных задач периодического обмена данными, таких как изменение правил обмена, добавление новых объектов или реквизитов к существующим, и является хорошей альтернативой для миграции существующих планов обмена на основе XML, которые ранее могли запускаться через COM.
Переходя на Linux, мы должны учитывать ряд важных особенностей, которые могут повлиять на нашу стратегию интеграции:
Одной из основных сложностей является необходимость переписывания кода, который ранее использовал COM-соединения. Часто такой код представляет собой "лапшу" или "говнокод", который трудно адаптировать к новой архитектуре. Нам предстоит полностью пересмотреть логику работы для отказа от COM-соединения и перенести ее на более современные механизмы, такие как HTTP-сервисы.
Для оптимизации работы и снижения нагрузки при получении данных из других баз мы можем реализовать механизмы кэширования. Это означает создание временных таблиц или регистров для хранения часто запрашиваемых данных. Если данные в кэше устарели, мы делаем новый запрос и обновляем их.
Нам необходимо убедиться, что лицензирование 1С:Предприятия корректно работает на Linux-сервере. Для аппаратных ключей защиты HASP существуют необходимые драйверы и программное обеспечение, которые мы должны установить и настроить в Linux-среде.
Внесение изменений в типовые конфигурации, особенно если они находятся на поддержке, или в базовые версии, может быть затруднительно. В таких случаях нам следует максимально использовать расширения конфигурации или механизмы запуска внешних обработок без изменения основной конфигурации.
В отличие от Windows, в Linux имена файлов и пути чувствительны к регистру. Это требует особо внимательного отношения к написанию кода, работающего с файловой системой, чтобы избежать ошибок.
В Linux используется единая корневая файловая система, а не отдельные диски. Пути к файлам будут выглядеть иначе (например, /opt/1c/data вместо C:\1c\data).
Некоторые объекты и методы 1С, тесно связанные с особенностями операционной системы Windows (например, ИзвлечениеТекста, ИнтернетСоединение, некоторые методы работы с панелью задач ОС), могут быть недоступны или работать некорректно в Linux.
1С на Linux может подключаться к различным внешним базам данных (MySQL, PostgreSQL, MS SQL) через ODBC. Это хорошо поддерживается и может быть использовано для более глубокой интеграции с данными, хранящимися вне 1С.
Переход от COM-соединения к современным методам интеграции — это неизбежный шаг при миграции на Linux. Мы видим, что платформа 1С предлагает несколько жизнеспособных альтернатив: HTTP-сервисы, OData, файловый обмен и запуск внешних обработок. Каждый из этих методов имеет свои преимущества и недостатки, и выбор конкретного подхода будет зависеть от сложности задачи, объема данных, требований к скорости и наличия ресурсов на переработку существующего кода.
Хотя переход может потребовать первоначальных усилий и инвестиций в переписывание логики, в долгосрочной перспективе он обеспечит более надежное, масштабируемое и безопасное решение, особенно в кроссплатформенных средах. Важно оценить свои потребности и возможности, чтобы выбрать оптимальный путь для интеграции ваших баз 1С в новой Linux-инфраструктуре.