Работа с внешними компонентами (ВК) в среде 1С:Предприятие часто преподносит сюрпризы при переходе от файлового режима к клиент-серверному. Особенно остро это ощущается, когда серверная часть функционирует под управлением ОС Linux. В данной статье мы подробно разберем, почему популярная компонента v8sqlite может отказываться работать на сервере, и пошагово реализуем механизм ее стабильного подключения и эксплуатации.
Разберем типичную ситуацию: в файловой базе вызов ПодключитьВнешнююКомпоненту("C:\v8sqlite.dll") проходит успешно. Однако в клиент-серверном варианте этот же код возвращает Ложь. Проанализируем причины этого поведения:
&НаСервере исполняется процессом rphost на удаленной машине. У сервера 1С нет доступа к вашему локальному диску C:..dll, так как это формат Windows. Ему необходим файл .so (Shared Object).usr1cv8) имеет ограниченные права в системе. Попытка загрузить библиотеку из произвольной папки может быть заблокирована политиками безопасности ОС.libc. Если компонента собрана в более новой ОС, чем та, что установлена на сервере, она не загрузится из-за конфликта версий.Чтобы компонента была доступна и клиенту, и серверу независимо от их местоположения, мы рекомендуем поместить бинарные файлы (для Windows x32, x64 и Linux x64) в общий макет. Рассмотрим, как правильно организовать программную выгрузку и подключение.
Для начала создадим общий макет с типом "Двоичные данные" (или поместим файлы в архив .zip, если файлов несколько). Теперь напишем функцию, которая будет определять нужный файл в зависимости от текущей платформы исполнения:
&НаСервере
Функция ОпределитьИмяФайлаПоПлатформе() Экспорт
СистемнаяИнформация = Новый СистемнаяИнформация;
Если СистемнаяИнформация.ТипПлатформы = ТипПлатформы.Windows_x86 Тогда
Возврат "v8sqlite_x32.dll";
ИначеЕсли СистемнаяИнформация.ТипПлатформы = ТипПлатформы.Windows_x86_64 Тогда
Возврат "v8sqlite_x64.dll";
ИначеЕсли СистемнаяИнформация.ТипПлатформы = ТипПлатформы.Linux_x86_64 Тогда
Возврат "libv8sqlite.so";
Иначе
ВызватьИсключение "Платформа не поддерживается компонентой v8sqlite";
КонецЕсли;
КонецФункции
Просто передать путь к файлу недостаточно. Рассмотрим правильный алгоритм: передача файла во временное хранилище, получение его на сервере и сохранение во временный файл в файловой системе сервера. Проанализируем код, который решает эту задачу:
&НаСервере
Функция ПодключитьКомпонентуНаСервере(АдресВоХранилище)
// Извлекаем двоичные данные из хранилища
ДанныеВК = ПолучитьИзВременногоХранилища(АдресВоХранилище);
// Генерируем уникальное имя временного файла с правильным расширением
ИмяФайлаНаСервере = ПолучитьИмяВременногоФайла(?(ПолучитьПлатформу() = "Linux", "so", "dll"));
ДанныеВК.Записать(ИмяФайлаНаСервере);
// Пытаемся подключить
Результат = ПодключитьВнешнююКомпоненту(ИмяФайлаНаСервере, "v8sqlite", ТипВнешнейКомпоненты.Native);
Если Результат Тогда
Попытка
ОбъектВК = Новый("AddIn.v8sqlite.v8sqlite");
Возврат ОбъектВК;
Исключение
ЗаписьЖурналаРегистрации("Ошибка ВК", УровеньЖурналаРегистрации.Ошибка,,, КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
Возврат Неопределено;
КонецПопытки;
КонецЕсли;
Возврат Неопределено;
КонецФункции
Важный нюанс: метод УстановитьВнешнююКомпоненту() на сервере не работает. Он предназначен для интерактивной установки расширения в браузер или тонкий клиент. На сервере мы работаем только с методом ПодключитьВнешнююКомпоненту().
Если после всех манипуляций ПодключитьВнешнююКомпоненту все равно возвращает Ложь на Linux, нам необходимо проверить зависимости библиотеки. Для этого воспользуемся терминалом Linux и утилитой ldd. Выполним команду:
ldd /tmp/libv8sqlite.so
Если в выводе вы видите строки вида /lib64/libc.so.6: version GLIBC_2.33 not found, это означает, что компонента была скомпилирована в более современной системе (например, Ubuntu 22.04), а ваш сервер 1С работает на более старой (например, CentOS 7 или Ubuntu 18.04).
Рассмотрим пути решения этой проблемы:
rphost. Рекомендуется использовать первый вариант.noexec в монтировании раздела).Часто программисты пытаются передать весь объем данных из SQLite в ТаблицуЗначений на сервер. Однако если файл SQLite находится на клиентской машине, а обработка данных должна идти на сервере, возникает проблема трафика. Рассмотрим, как оптимизировать этот процесс.
Выясним причину медленной работы: передача больших массивов между клиентом и сервером нагружает сеть. Мы рекомендуем использовать формат JSON. Компонента v8sqlite поддерживает выгрузку результата запроса напрямую в строку JSON. Проанализируем пример:
// На стороне клиента (где лежит файл БД)
РезультатJSON = ВК.ВыполнитьЗапрос(ТекстЗапроса, "JSON");
// Передаем строку на сервер
ОбработатьДанныеНаСервере(РезультатJSON);
// На сервере разбираем штатными средствами
&НаСервере
Процедура ОбработатьДанныеНаСервере(ДанныеJSON)
Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(ДанныеJSON);
МассивДанных = ПрочитатьJSON(Чтение);
// Теперь у нас есть массив структур, доступный для обработки
КонецПроцедуры
Разберем несколько важных моментов, которые помогут избежать блокировок и потерь данных при работе в многопользовательской среде:
PRAGMA journal_mode=WAL;.BEGIN TRANSACTION; и COMMIT;. Без этого SQLite будет создавать транзакцию для каждой строки, что замедлит работу в сотни раз.ДвоичныеДанные 1С в параметры запроса. Компонента корректно обрабатывает их на нативном уровне без лишнего кодирования в Base64.Подводя итог, можно сказать, что связка 1С и SQLite через нативную компоненту — это мощный инструмент для работы с локальными кэшами и внешними данными. Главное — помнить о разнице платформ и корректно управлять жизненным циклом файлов библиотеки в файловой системе сервера.