Интеграция платформы 1С с хранилищем 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 запускаем простейшее хранилище,
идеально подходящее для разработчиков и экспериментов:
При выполнении команды будет показана информация, по каким адресам доступны сервисы S3.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. Это значения по умолчанию. При желании, можно ещё создать у регистра реквизит булевого типа и указать его в нижнем поле, для более гибкого управления записью, но нам это усложенение не нужно и оставляем как есть.
Далее, самостоятельно напишите любой код, заполняющий и читающий данные из ресурса типа ХранилищеЗначения, я перегружать статью деталями не буду.
Конфигурация без хранилища
Чтобы сравнить что было и что стало, давайте пока вообще не будем трогать настройки хранилища и запишем в регистр несколько записей с двоичными значениями (в моём случае это фотографии) и посмотрим с помощью 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С-ников о том, что хранение двоичных данных в таблицах замедляет выполнение запросов: на самом деле блобы лежат в отдельной физической таблице, и они естественно во время выполнения запроса к обычным данным не считываются с диска и не могут ухудшать план его выполнения.
Смотрим, что же в таблице регистра:

В бинарное поле записались не все загруженные данные, а всего 64 байта. Первые 16 байт это явно заголовок, указывающий что данные записаны в некое хранилище. Поищем, где же оно это хранилище? По размеру данных легко находим таблицу, это binarydata. Можно сперва подумать что это и есть внутреннее хранилище, которое используется по умолчанию когда даже не введены настройки для хранения двоичных данных, но на самом деле нет. На всякий случай испробуем запрос выше и убеждаемся что для этой таблицы тоже применяется стратегия EXTENDED для хранения в отдельной таблице TOAST.
Может быть так сработало из-за того, что мы в конфигураторе указали "Использовать" в опции "Использование хранения в хранилище двоичных данные"? Если переключить на "Не использовать" и перезагрузить в регистр файлы, то убеждаемся, что ничего не поменялось. Зато начала распухать таблица binarydata и в ней явно остались старые данные вместе с новыми загруженными! С настройками новой платформы по умолчанию как-то уже нехорошо становится.
Возможно так происходит потому, что технология сырая и текущая версия платформы на момент написания (8.3.27.1719) не совсем корректно отрабатывает настройки.
Настройка на внутреннее хранилище
Хранилище двоичных данных можно настроить как в конфигураторе (Администрирование - Управление хранилищами двоичных данных) так и в тонком клиенте. Больше функций в стандартной обработке тонкого клиента:



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

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


В общем, не угадал: ни то, ни другое, получили битые ссылки. Пока никто не увидел, вернём настройку на место... Уф, пронесло, картинки снова доступны и на месте )
Настройка базы на хранилище S3
Для начала, залезем через браузер в консоль управления MinIO S3 (адрес он написал куда) и c помощью кнопки Create Bucket добавим контейнер с именем test:

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



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

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

В таблице 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 хранилища. Именно это значение прописано в поле данных:

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