Представляю вашему вниманию мини-демонстрацию технологии, позволяющую минимальным количеством кода осуществлять обмен информацией между различными ИС. В данном примере взаимодействие с сервером передачи сообщений реализовано в конфигурации 1С.
Реализован групповой "чат", имеющий минимальный функционал:
- просмотр последних сообщений и имена их авторов;
- отправку новых сообщений;
Для демонстрации результатов можно запустить несколько экземпляров ИБ одновременно, наблюдая передачу данных между ними.
Техническая реализация не имеет ничего общего с "правильной" архитектурой решения подобных задач, и должна рассматриваться только как демонстрация возможностей подсистемы обмена сообщениями.
Реализация
Демонстрационная база содержит основную конфигурацию, собственно где и реализована общая форма "чат", в которой описана вся его специфичная логика, взаимодействуя с библиотечными функции платформы DESP, для отправки и получения сообщений.
Платформа DESP состоит из ядра сервиса (brake), написано на Go. Реализует такие механизмы как:
- Получение, хранение, отдачу сообщений посредством вызова RPC-методов ядра платформы (JSON-RPC 2.0);
- Вызов удаленных процедур (RPC), реализованных на JavaScript, расположенных на сервере;
- Вызов удаленных процедур (RPC), реализованных в "подключенных" к DESP базах 1С (на языке 1С, при этом публиковать http- или web-сервисы не требуется);
- Доступ к хранилищу ключ-значение;
- Контроль доступа к RPC и очередям сообщений, посредством ключа авторизации;
- Параметризация "длинны" очереди сообщений (по двум характеристикам: максимальный размер в байтах и максимальная длительность хранения сообщения, задается на стороне конфигурации сервера desp);
- Регистрация измененных объектов в очереди для дальнейшей сериализации и отправки в одну из очередей, правила "конвертации" описываются программным кодом ("алгоритмом", программный код 1С);
- Чтение очереди и десериализация объектов по правилам ("алгоритмам", программный код 1С);
- Минимальный мониторинг состояния очередей, рабочих потоков 1С исполнения PRC-методов;
(в этой статье разбираются только возможности из первого пункта, и косвенно задействованы механизмы, перечисленные в пунктах, выделенные жирным шрифтом)
Та часть подсистемы DESP, которая реализуется на стороне базы 1С представлена:
- "Библиотечным" расширением "DESP" (минимальная требуемая версия платформы 1С - 8.3.17, не предполагает изменений при реализации бизнес-задач), содержит процедуры/функции для простого использования основных возможностей платформы;
- Дополнительным расширением "DESP_config", содержащим:
- Параметры подключения к серверу brake (ядро платформы DESP): адрес, порт, ключ авторизации;
- Программный код и конфигурацию реализованных методов RPC в базе 1С;
- Программный код для интерпретации сообщений чтения сообщений.
Чат
Практически, количество "клиентов" искусственно не ограничено, и может составлять сотни и даже тысячи без дополнительных оптимизаций и доработок на весьма слабом серверном железе, на котором запущена серверная часть DESP.
Логика взаимодействия:
При открытии формы чата генерируется псевдослучайное имя пользователя, которое затем можно указать самостоятельно в форме, вычисляется номер сообщения очереди, с которого нужно вычитать данные и производится их отображение на форме, подключается обработчик ожидания для периодического вычитывания и отображения новых сообщений.
&НаКлиенте
Перем idКрайнегоСообщения;
&НаКлиенте
Процедура ПриОткрытии(Отказ)
ГСЧ = Новый ГенераторСлучайныхЧисел();
МоеИмя = "Аноним_"+ГСЧ.СлучайноеЧисло(1,999);
ОбновитьIdПервогоСообщенияДляЧтения();
ПрочитатьНовыеСообщения();
ПодключитьОбработчикОжидания("ПрочитатьНовыеСообщения", 1, Ложь);
КонецПроцедуры
Код процедуры получения номера сообщения, с которого нужно будет начать отображение на форму:
&НаКлиенте
Процедура ОбновитьIdПервогоСообщенияДляЧтения()
idКрайнегоСообщения = 0;
П = Новый Структура();
П.Вставить("topic", "chat");
П.Вставить("limit", 1);
Результат = desp_УдаленныйВызовПроцедур.ВызватьМетод("brake_pull_messages", П);
Если Результат<>Неопределено Тогда
Для Каждого ЭлементРезультата Из Результат Цикл
idКрайнегоСообщения = ЭлементРезультата.id;
КонецЦикла;
КонецЕсли;
idКрайнегоСообщения = Макс(1, idКрайнегоСообщения-10);
КонецПроцедуры
Далее, код процедуры вычитывания и отображения новых сообщений, за один раз не более 50 штук:
&НаКлиенте
Процедура ПрочитатьНовыеСообщения()
Перем НоваяСтрокаТаблицы;
П = Новый Структура();
П.Вставить("topic", "chat");
П.Вставить("off", idКрайнегоСообщения);
П.Вставить("limit", 50);
Результат = desp_УдаленныйВызовПроцедур.ВызватьМетод("brake_pull_messages", П);
Если Результат<>Неопределено Тогда
Для Каждого ЭлементРезультата Из Результат Цикл
Попытка
ЧтениеJSON = Новый ЧтениеJSON();
ЧтениеJSON.УстановитьСтроку(ЭлементРезультата.payload);
РезультатВыполнения = ПрочитатьJSON(ЧтениеJSON);
Если Переписка.Количество()>50 Тогда
Переписка.Удалить(0);
КонецЕсли;
НоваяСтрокаТаблицы = Переписка.Добавить();
НоваяСтрокаТаблицы.Автор = РезультатВыполнения.user;
НоваяСтрокаТаблицы.Сообщение = РезультатВыполнения.message;
НоваяСтрокаТаблицы.МоеСообщение = Истина;
Исключение
КонецПопытки;
idКрайнегоСообщения = ЭлементРезультата.id + 1;
КонецЦикла;
Элементы.Переписка.ТекущаяСтрока = Переписка.Индекс(НоваяСтрокаТаблицы);
КонецЕсли;
КонецПроцедуры
И в заключении, код процедуры отправки новых сообщений:
&НаКлиенте
Процедура КомандаОтправить(Команда)
СтруктураСДанными = Новый Структура();
СтруктураСДанными.Вставить("user", МоеИмя);
СтруктураСДанными.Вставить("message", Сообщение);
ЗаписьJSON = Новый ЗаписьJSON();
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, СтруктураСДанными);
Сообщения = Новый Массив();
Сообщения.Добавить(ЗаписьJSON.Закрыть());
П = Новый Структура();
П.Вставить("topic", "chat");
П.Вставить("messages", Сообщения);
desp_УдаленныйВызовПроцедур.ВызватьМетод("brake_push_messages", П);
Сообщение = "";
КонецПроцедуры
В данном примере взаимодействие с сервисом происходит исключительно синхронно, поэтому, такие моменты, как медленное соединение с "сервисом" и/или большой объем сообщений могут "замораживать" интерфейс, а его сетевая недоступность останавливает интерфейс Предприятия и сообщает об ошибке...
(Скорей всего хорошим решением для получения и отправки сообщений чата было бы не прямое (рилтайм) взаимодействие с методами сервера - brake, но взаимодействие с ними со стороны сервера 1C, в фоновых заданиях, и DESP это предусматривает! Однако, в данной статье рассмотрен не будет).
Как видите, технически всё достаточно просто. Из "необычного" в коде нужно обратить внимание на вызовы функции вида "desp_УдаленныйВызовПроцедур.ВызватьМетод()", - это обертка для обращения к сервису, где первый параметр, это имя вызываемого метода, второй, - именованные параметры, передаваемые для вызываемого метода. Т.е. все обращения к сервису осуществляются исключительно через эту функцию, и соответственно по стандарту (JSON-RPC 2.0), что дает возможность использовать сервис из кода других ЯП, скриптов.
Ответы на некоторые вопросы:
- Зачем оно мне, если у нас есть работающий "1С:Сервер взаимодействия" / Kafka / RabbitMQ?
- Тогда незачем.
- Сообщения сжимаются/шифруются?
- Передача и получение сообщений происходит по https. Сообщение на дисках сервера brake "лежат" в незашифрованном виде.
- Что такое DESP, а что такое brake?
- DESP - комплексное решение, состоящие из ядра (brake) + расширений для платформы 1С. brake - сервис, написанный на Go, реализующий функции, требующие максимальной производительности, потребляя минимальное количество ресурсов, там же располагаются данные очередей, JS-скрипты, конфигурационный файл сервиса.
- На что больше похож DESP в части работы с очередями?
- Идеология работы с очередями была подсмотрена у Kafka.
- Данные реплицируются с целью повышения доступности и/или увеличения производительности?
- Не реализовано на данный момент.
- Будет работать только через "Облако"?
- Для реальных проектов предполагается развертывание сервера в локальной сети.
- Можно ли программно создавать новые очереди?
- Нет, очереди задаются в конфигурационном файле сервиса, вместе с параметрами ротации (удаления устаревших данных), правами доступа и т.д.
- Нужно ли публиковать базу в web, чтобы она могла взаимодействовать с платформой?
- Нет, это не требуется. Всё взаимодействие происходит через запросы к платформе, никаких webhook не предусмотрено и не планируется.