diamond АШ Tlg

Интеграция платформы 1С с хранилищем S3. Разбор механизма

В платформе 1С 8.3.27 добавили прозрачную интеграция для хранения двоичных данных в отдельном хранилище, поддерживающем стандартный протокол S3.

Введение

Почитать что такое S3 можно, например, здесь: S3. Понятно, что с хранилищами S3 из 1С можно было работать и раньше, через протокол http с помощью HTTPСоединение. В данной статье будет разбор как работает новый механизм интеграции с S3 на уровне платформы, когда программисту вообще ничего специально писать не нужно, а платформа (начиная с 8.3.27) сама размещает большие данные в хранилище S3 и извлекает их оттуда обратно.

Реквизиты

Для экспериментов нам понадобятся:

  • Cвободный компьютер, подойдёт практически любой современный не маргинальный Linux с графическим окружением
  • Поднять пустую информационную базу 1С в клиент-серверном режиме (8.3.27.1719): Cервер 1С Клиент 1С Клиент 1С (др.способ) Postgres PostgresPro (др. способ) Лицензия разработчика 1С
  • Установите консоль администрирования DBeaver (предполагается что вы умеете им пользоваться), например из flathub:
    flatpak install app/io.dbeaver.DBeaverCommunity/x86_64/stable
  • Поднять хранилище S3: с помощью контейнеризации podman или docker запускаем простейшее хранилище, идеально подходящее для разработчиков и экспериментов:
    podman run --name s3 -p 9000:9000 -p 9001:9001 \                                                                                                    ✔ 
    	-e "MINIO_ROOT_USER=minioadmin" \
    	-e "MINIO_ROOT_PASSWORD=minioadmin" \
    	quay.io/minio/minio server /data --console-address ":9001"
    При выполнении команды будет показана информация, по каким адресам доступны сервисы S3.

В конфигурации информационной базы создайте любой объект, содержащий реквизит типа ХранилищеЗначения, в который и нужно будет записывать двоичные данные и которые являются целевым предметом для хранения в S3. Например такой регистр сведений:

Регистр сведений для опытов

Прямоугольником выделены важные свойства, которые напрямую влияют на результаты опытов с хранилищем S3. Это значения по умолчанию. При желании, можно ещё создать у регистра реквизит булевого типа и указать его в нижнем поле, для более гибкого управления записью, но нам это усложенение не нужно и оставляем как есть.

Далее, самостоятельно напишите любой код, заполняющий и читающий данные из ресурса типа ХранилищеЗначения, я перегружать статью деталями не буду.

Конфигурация без хранилища

Чтобы сравнить что было и что стало, давайте пока вообще не будем трогать настройки хранилища и запишем в регистр несколько записей с двоичными значениями (в моём случае это фотографии) и посмотрим с помощью DBeaver как оно легло в СУБД. Т.к. конфигурация изначально была пустая, то таблица с регистром легко находится, у меня это _inforg53. Проверим стратегию хранения блобов:

SELECT attname, attstorage FROM pg_attribute 
WHERE attrelid = '_inforg53'::regclass AND attname = '_fld55';

attname|attstorage|
-------+----------+
_fld55 |x         |

Этот результат означает, что применяется оптимальная стратегия EXTENDED для хранения поля _fld55 (Фото) типа bytea: если размер бинарных данных превышает 2048 байт, то данные записываются в отдельную таблицу TOAST. Подробнее об этом можно почитать здесь: TOAST. Между прочим, это опровергает популярное мнение в среде 1С-ников о том, что хранение двоичных данных в таблицах замедляет выполнение запросов: на самом деле блобы лежат в отдельной физической таблице, и они естественно во время выполнения запроса к обычным данным не считываются с диска и не могут ухудшать план его выполнения.

Смотрим, что же в таблице регистра:

Запись без настройки S3

В бинарное поле записались не все загруженные данные, а всего 64 байта. Первые 16 байт это явно заголовок, указывающий что данные записаны в некое хранилище. Поищем, где же оно это хранилище? По размеру данных легко находим таблицу, это binarydata. Можно сперва подумать что это и есть внутреннее хранилище, которое используется по умолчанию когда даже не введены настройки для хранения двоичных данных, но на самом деле нет. На всякий случай испробуем запрос выше и убеждаемся что для этой таблицы тоже применяется стратегия EXTENDED для хранения в отдельной таблице TOAST.

Может быть так сработало из-за того, что мы в конфигураторе указали "Использовать" в опции "Использование хранения в хранилище двоичных данные"? Если переключить на "Не использовать" и перезагрузить в регистр файлы, то убеждаемся, что ничего не поменялось. Зато начала распухать таблица binarydata и в ней явно остались старые данные вместе с новыми загруженными! С настройками новой платформы по умолчанию как-то уже нехорошо становится.

Возможно так происходит потому, что технология сырая и текущая версия платформы на момент написания (8.3.27.1719) не совсем корректно отрабатывает настройки.

Настройка на внутреннее хранилище

Хранилище двоичных данных можно настроить как в конфигураторе (Администрирование - Управление хранилищами двоичных данных) так и в тонком клиенте. Больше функций в стандартной обработке тонкого клиента:

Настройки внутреннего хранилища Настройки внутреннего хранилища Настройки внутреннего хранилища

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

Настройки внутреннего хранилища

Перезагрузим файлы в регистр. Смотрим, что поменялось: в таблице _inforg53 поменялись только ссылки в бинарном поле, зато таблица binarydata очистилась! Куда делись красивые фотки? Они выгрузились из СУБД и записались в файловую систему на сервере приложений. На досуге поищите там каталог BinDataStrg в каталоге /home/usr1cv8.

В чём получается выгода? В том, что программисту вообще больше не нужно заморачиваться и можно пихать реквизиты типа ХранилищеЗначения вообще куда удобно - платформа сама определится и запишет его не в СУБД, а в файловую систему (согласно настройкам конечно) и так же без мороки прочитает его обратно.

Проведём опыт: удалим настройку хранения в хранилище бинарных настроек, чтобы стало как в начале. Интересно, файлы переедут обратно в СУБД или просто обнулятся?

Ошибка отсутствия внутреннего хранилища Поздравляю Шарик, ты балбес!

В общем, не угадал: ни то, ни другое, получили битые ссылки. Пока никто не увидел, вернём настройку на место... Уф, пронесло, картинки снова доступны и на месте )

Настройка базы на хранилище S3

Для начала, залезем через браузер в консоль управления MinIO S3 (адрес он написал куда) и c помощью кнопки Create Bucket добавим контейнер с именем test:

MinIO бакет test

Добавим новое хранилище:

S3 S3 S3

В этой настройке вам может показаться, что можно записывать параллельно сразу в 2-3 хранилища:

S3

К сожалению, только показалось - "в трёх экземплярах" записывать нельзя.

Все старые фотки на месте. Перезальём одну фотку и посмотрим что произошло. Во-первых, в хранилище MinIO сразу прилетел блоб со значением типа ХранилищеЗначения:

S3

В таблице binarydata по-прежнему пусто, зато в binarydatastoragecontent появились интересные строки:

select f_type, f_str1, f_num5, f_vstr1, f_vstr2, f_vstr3, f_vstr4 from binarydatastoragecontent;;

f_type          |f_str1              |f_num5|f_vstr1               |f_vstr2   |f_vstr3   |f_vstr4|
----------------+--------------------+------+----------------------+----------+----------+-------+
STORE           |                    |  2048|                      |          |          |       |
STORE           |minio               |  2048|http://magic:9000/test|minioadmin|minioadmin|RU     |
DEFAULT         |                    |     0|                      |          |          |       |

Здесь и хранятся все настройки двоичных хранилищ, включая S3. Обратите внимание, имя и пароль для доступа к хранилищу S3 лежат в незашифрованном виде! Если у вас "кровавый энтерпрайз" и ваши безопасники прочтут эти строки, то дальше для вас эта тема скорее всего на этом будет закрыта, особенно если собирались хранить конфиденциальные файлы. Сорян коллеги, я не буду скрывать то что имеем.

Проведём снова опыт: удалим настройку хранилища S3 и снова его восстановим. Те данные, что лежали во внутреннем хранилище, никуда не делись и нормально открываются. Зато с данными на S3 беда:

Ошибка отсутствия внутреннего хранилища

ОБРАТИТЕ ВНИМАНИЕ: после восстановления настройки ошибка не исчезает, связи с хранилищем S3 потеряны навсегда!

Поздравляю Шарик, ты балбес! Окончательно!

Причина как видится в битой ссылке. В таблице binarydatastoragecontent при создании настройки S3 в поле f_key прописывается новый id хранилища. Именно это значение прописано в поле данных:

Запись в S3
  • 1 - стандартный заголовок (16 байт)
  • 2 - ключ хранения данных в S3 (16 байт), вернитесь посмотреть картинку выше и убедитесь что в бакете те же значения в виде строки.
  • 3 - размер блоба в байтах, int64_t (8 байт)
  • 4 - идентификатор хранилища (16 байт) = поле f_key в таблице binarydatastoragecontent

Таким образом, для восстановления битых ссылок после неожиданной оказии с настройками нужно подменить 16 байт (блок 4) на новый идентификатор хранилища. У кого есть время и желание, думаю легко смогут написать утилиту восстановления связей на любимом языке программирования. Если готовы поделиться, скиньте мне инфу в личку, с удовольствием размещу ссылку на неё.

Выгрузка в DT

Тут всё ожидаемо - данные из хранилищ перекочевали в таблицу binarydata. Таким образом выгрузка DT будет включать в себя терабайты данных из хранилища, если они у вас будут.

Заключение

Сложно что-либо посоветовать. Лично мне использовать такое страшно. Если у вас есть безопасники, то и думать не придётся (см. пассаж про открытые пароли в таблице настроек).