Как настроить работу внешней компоненты v8sqlite в клиент-серверной базе 1С на Linux

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Работа с внешними компонентами (ВК) в среде 1С:Предприятие часто преподносит сюрпризы при переходе от файлового режима к клиент-серверному. Особенно остро это ощущается, когда серверная часть функционирует под управлением ОС Linux. В данной статье мы подробно разберем, почему популярная компонента v8sqlite может отказываться работать на сервере, и пошагово реализуем механизм ее стабильного подключения и эксплуатации.

Анализ проблемы: почему "на клиенте работает, а на сервере — нет"

Разберем типичную ситуацию: в файловой базе вызов ПодключитьВнешнююКомпоненту("C:\v8sqlite.dll") проходит успешно. Однако в клиент-серверном варианте этот же код возвращает Ложь. Проанализируем причины этого поведения:

  1. Разделение контекстов: В файловой базе клиент и сервер — это один процесс. В клиент-серверной базе код &НаСервере исполняется процессом rphost на удаленной машине. У сервера 1С нет доступа к вашему локальному диску C:.
  2. Разница операционных систем: Если сервер работает на Linux, он физически не может загрузить файл .dll, так как это формат Windows. Ему необходим файл .so (Shared Object).
  3. Права доступа: Процесс сервера 1С (обычно пользователь usr1cv8) имеет ограниченные права в системе. Попытка загрузить библиотеку из произвольной папки может быть заблокирована политиками безопасности ОС.
  4. Зависимости библиотек (GLIBC): В Linux нативные компоненты жестко привязаны к версии системной библиотеки libc. Если компонента собрана в более новой ОС, чем та, что установлена на сервере, она не загрузится из-за конфликта версий.

Шаг 1. Организация хранения компоненты в конфигурации

Чтобы компонента была доступна и клиенту, и серверу независимо от их местоположения, мы рекомендуем поместить бинарные файлы (для Windows x32, x64 и Linux x64) в общий макет. Рассмотрим, как правильно организовать программную выгрузку и подключение.

Для начала создадим общий макет с типом "Двоичные данные" (или поместим файлы в архив .zip, если файлов несколько). Теперь напишем функцию, которая будет определять нужный файл в зависимости от текущей платформы исполнения:


&НаСервере
Функция ОпределитьИмяФайлаПоПлатформе() Экспорт
    СистемнаяИнформация = Новый СистемнаяИнформация;
    Если СистемнаяИнформация.ТипПлатформы = ТипПлатформы.Windows_x86 Тогда
        Возврат "v8sqlite_x32.dll";
    ИначеЕсли СистемнаяИнформация.ТипПлатформы = ТипПлатформы.Windows_x86_64 Тогда
        Возврат "v8sqlite_x64.dll";
    ИначеЕсли СистемнаяИнформация.ТипПлатформы = ТипПлатформы.Linux_x86_64 Тогда
        Возврат "libv8sqlite.so";
    Иначе
        ВызватьИсключение "Платформа не поддерживается компонентой v8sqlite";
    КонецЕсли;
КонецФункции

Шаг 2. Корректное подключение на стороне сервера

Просто передать путь к файлу недостаточно. Рассмотрим правильный алгоритм: передача файла во временное хранилище, получение его на сервере и сохранение во временный файл в файловой системе сервера. Проанализируем код, который решает эту задачу:


&НаСервере
Функция ПодключитьКомпонентуНаСервере(АдресВоХранилище)
    // Извлекаем двоичные данные из хранилища
    ДанныеВК = ПолучитьИзВременногоХранилища(АдресВоХранилище);
    
    // Генерируем уникальное имя временного файла с правильным расширением
    ИмяФайлаНаСервере = ПолучитьИмяВременногоФайла(?(ПолучитьПлатформу() = "Linux", "so", "dll"));
    ДанныеВК.Записать(ИмяФайлаНаСервере);
    
    // Пытаемся подключить
    Результат = ПодключитьВнешнююКомпоненту(ИмяФайлаНаСервере, "v8sqlite", ТипВнешнейКомпоненты.Native);
    
    Если Результат Тогда
        Попытка
            ОбъектВК = Новый("AddIn.v8sqlite.v8sqlite");
            Возврат ОбъектВК;
        Исключение
            ЗаписьЖурналаРегистрации("Ошибка ВК", УровеньЖурналаРегистрации.Ошибка,,, КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
            Возврат Неопределено;
        КонецПопытки;
    КонецЕсли;
    
    Возврат Неопределено;
КонецФункции

Важный нюанс: метод УстановитьВнешнююКомпоненту() на сервере не работает. Он предназначен для интерактивной установки расширения в браузер или тонкий клиент. На сервере мы работаем только с методом ПодключитьВнешнююКомпоненту().

Шаг 3. Решение проблем с зависимостями в Linux (GLIBC)

Если после всех манипуляций ПодключитьВнешнююКомпоненту все равно возвращает Ложь на 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).

Рассмотрим пути решения этой проблемы:

Шаг 4. Оптимизация обмена данными между SQLite и 1С

Часто программисты пытаются передать весь объем данных из SQLite в ТаблицуЗначений на сервер. Однако если файл SQLite находится на клиентской машине, а обработка данных должна идти на сервере, возникает проблема трафика. Рассмотрим, как оптимизировать этот процесс.

Выясним причину медленной работы: передача больших массивов между клиентом и сервером нагружает сеть. Мы рекомендуем использовать формат JSON. Компонента v8sqlite поддерживает выгрузку результата запроса напрямую в строку JSON. Проанализируем пример:


// На стороне клиента (где лежит файл БД)
РезультатJSON = ВК.ВыполнитьЗапрос(ТекстЗапроса, "JSON");

// Передаем строку на сервер
ОбработатьДанныеНаСервере(РезультатJSON);

// На сервере разбираем штатными средствами
&НаСервере
Процедура ОбработатьДанныеНаСервере(ДанныеJSON)
    Чтение = Новый ЧтениеJSON;
    Чтение.УстановитьСтроку(ДанныеJSON);
    МассивДанных = ПрочитатьJSON(Чтение);
    // Теперь у нас есть массив структур, доступный для обработки
КонецПроцедуры

Дополнительные советы для стабильной работы

Разберем несколько важных моментов, которые помогут избежать блокировок и потерь данных при работе в многопользовательской среде:

  1. Режим WAL (Write-Ahead Logging): Если с одной базой SQLite одновременно работают несколько сеансов 1С, обязательно включите режим WAL. Это позволит читающим процессам не блокировать записывающие. Выполните команду сразу после открытия соединения: PRAGMA journal_mode=WAL;.
  2. Использование транзакций: При массовой записи данных (например, загрузка 10 000 строк из 1С в SQLite) обязательно обрамляйте цикл командами BEGIN TRANSACTION; и COMMIT;. Без этого SQLite будет создавать транзакцию для каждой строки, что замедлит работу в сотни раз.
  3. Работа с BLOB: Если вам нужно сохранить в SQLite картинки или файлы, передавайте их напрямую как ДвоичныеДанные 1С в параметры запроса. Компонента корректно обрабатывает их на нативном уровне без лишнего кодирования в Base64.

Подводя итог, можно сказать, что связка 1С и SQLite через нативную компоненту — это мощный инструмент для работы с локальными кэшами и внешними данными. Главное — помнить о разнице платформ и корректно управлять жизненным циклом файлов библиотеки в файловой системе сервера.

← На главную