Отправка и получение данных из мобильного приложения через DataProvider
Как я говорил, с мобильным приложением есть две проблемы.
-
Первая – нет параллельных фоновых заданий, нам приходится самим управлять их последовательным запуском.
-
Вторая – блокировки на таблицах, мы не можем одновременно записывать данные и обеспечить текущую работу пользователю.
Чтобы решить эти две проблемы, мы вынесли отправку и получение данных во внешнее приложение.
Раньше для передачи данных из мобильного приложения мы использовали тот же подход, что и для десктопного приложения.
-
При возникновении события (записи объекты), регистрировали это событие в специальном справочнике или в плане обмена;
-
В фоновом задании выгребали все зарегистрированные события из плана обмена или справочника, формировали текст сообщения и отправляли через RabbitMQ.
Теперь при возникновении события сразу формируем сообщение и высылаем в DataProvider.
-
Никаких фоновых процессов, связанных с отправкой, в 1С больше нет.
-
DataProvider сам при появлении связи отправляет это сообщение в RabbitMQ.
-
Так как пользователь практически никогда не может генерировать события чаще, чем раз в секунду, то нет проблемы в том, что мы в этой же транзакции записи объекта сразу формируем сообщение и сразу его передаем – пользователь никого не блокирует, потому что он на своем устройстве в базе работает один.
Раньше для получения данных из мобильного приложения мы использовали тот же подход, что и для десктопного приложения.
-
Мы периодически опрашивали RabbitMQ в фоновом задании и забирали сообщения;
-
В отдельном фоновом задании пытались формировать объекты по этим сообщениям – при этом сталкивались со всем набором проблем файловой базы.
Теперь забором и хранением сообщений в базе SQLlite занимается DataProvider.
-
Забором сообщений занимается DataProvider и хранит их у себя бесконечно долго – до востребования мобильным приложением БИТ.MDT;
-
DataProvider понимает по сообщению, что это за сообщение, и, если оно должно храниться в базе SQLite, то сразу его туда складывает вообще без участия 1С;
-
1С, когда ему это удобно, берет нужные данные из DataProvider, с которым у него всегда есть связь.
Пример работы приложения
На слайде показан пример пакетной передачи марок из центральной базы в мобильном приложении и складывание в базу SQLite.
Слева показан текст сообщения, в котором указана информация сразу по нескольким маркам. Синей обводкой я выделил ту информацию, которая относится к одной марке.
Обратите внимание, что хотя это JSON, он без названий полей – это способ побороться с объемом передаваемых сообщений. Заголовки полей для марок нам не нужны, потому что мы и так знаем последовательность реквизитов
Поэтому боремся за место.
Сообщение через RabbitMQ пришло в DataProvider, и тот сразу нераспарсенным складывает его в базу SQLite.
DataProvider ничего не знает про структуру объектов 1С – он просто разбирает массив из JSON в конкретный элемент и складывает сообщения в базу данных в отдельные записи.
В отдельную колонку складывает имя объекта метаданных и его GUID, и теперь, когда нам этот объект из 1С потребуется, мы его по GUID быстро найдем и только в этот момент его распарсим и создадим объект в 1С.
Как это выглядит при сканировании марки.
-
Мы просканировали марку на устройстве, поискали в 1С – ее там не оказалось.
-
Мы идем в базу SQLite, там есть типовой регистр сведений «Штрихкоды объектов», который хранит соответствие между штрихкодом и GUID объектов системы.
-
По этому штрихкоду нашли GUID соответствующего элемента и дальше по нему нашли текст нужного сообщения.
-
Создали элемент справочника штрих-кода упаковок в 1С и вернули его в вызвавшую процедуру.
С точки зрения прикладной логики это выглядит так: получить штрихкод упаковки для марки с таким-то кодом. На выходе он получает ссылку на элемент справочника 1С, но под капотом программа лезет в базу SQLite, находит соответствующее сообщение, создает элемент справочника «Штрихкод упаковок» в 1С и возвращает на него ссылку. Вот так выглядит извлечение из базы SQLite по требованию.
Поэтому в мобильной базе на конкретном устройстве содержатся только те марки, которые пользователь просканировал. А один человек не может просканировать 7 миллионов марок.
Таким образом мы решили проблему с объемом базы, которая лежит в мобильном приложении.
Общая архитектура системы v1.0
БИТ.MDT состоит из нескольких частей.
-
расширение, которое встраивается в типовую конфигурацию;
-
мобильное приложение, которое работает на ТСД;
-
транспорт между этими компонентами обеспечивается через:
-
брокер сообщений на базе RabbitMQ;
-
и через Web-сервис.
-
Что дает использование RabbitMQ:
-
RabbitMQ позволяет доставлять сообщения даже тогда, когда какие-то участники обмена вне зоны доступа, в том числе, когда центральная база недоступна. Например, мы обновляем центральную базу ERP, – база большая, обновление длится несколько часов, но в это время с двух ТСД можно собирать один заказ.
-
ТСД обмениваются информацией напрямую через брокер между собой, даже если в этот момент центральная база недоступна. Это позволяет обеспечить работу 24/7 на ТСД.
-
Кроме того, RabbitMQ позволяет гибко маршрутизировать сообщения между базами и доставлять их до устройств центральной базы тогда, когда они становятся доступными и выходят на связь.
Web-сервис используется только при первоначальной инициализации, когда подключают новый ТСД и нужно однократно передать на него большой объем информации. Тогда мы используем Web-сервис, чтобы 7 гигабайт прокачать на ТСД за раз.
Обновление БИТ.MDT из DataProvider
Первый лайфхак – мы используем обновление через удаление вместе с данными. Мы, как правило, не обновляем мобильное приложение. Вместо этого мы удаляем старое приложение и устанавливаем новую версию программы с последующей инициализацией.
Если бы мы обновлялись, у нас была бы отдельная сложно решаемая задача – как синхронизировать данные между ста устройствами, как убедиться, что у всех одинаковые данные. Задача сложная и мы ее решать не беремся.
Мы делаем просто – каждый раз, когда нужно обновиться, то мы все стираем, забываем о том, что было на мобильном устройстве и устанавливаем приложение заново. Заново скачиваем актуальную базу SQLite из центральной базы и начинаем работать с чистого листа. Таким образом мы добиваемся, что при достаточно частом обновлении, у нас данные синхронизированы на разных устройствах.
Как работает DataProvider для обновления. Мы из центральной базы где-то в интернете или во внутреннем хранилище, либо на Web-сервисе публикуем файл-манифест, в котором указано:
-
какие устройства;
-
на какую версию платформы нужно обновить;
-
и где для этого взять apk-файл.
DataProvider знает, что файл-манифест лежит в таком-то месте по такой-то ссылке, и периодически следит за ним.
-
Если DataProvider видит, что файл-манифест поменялся, и устройство нужно обновить, он передает через внешнюю компоненту в мобильное приложение сообщение: «Я тебя скоро буду обновлять, предупреди пользователя».
-
Пользователь получает предложение обновиться и обновляет мобильное приложение.
Это нам позволило прямо из центральной базы 1С:ERP через справочник мобильных устройств определять: «Эту версию apk раскидай на эти устройства по списку». Теперь не надо ходить и собирать физически устройства.
Все делается снаружи, управляется через интернет. Получилась MDT-система на минималках.
Большой пак дополнений март 2021: регламентные задания, распознавание дат и чисел, оповещения, поля с автозаполнением и многое, многое другое
Релиз с огромным количеством дополнений. Дополнение к основной статье Simple UI: https://infostart.ru/public/1153616/
Перечень изменений:
1. Оптическое распознавание дат в разных форматах
2. Оптическое распознавание чисел в разных форматах
3. Запуск кода из кода синхронно/асинхронно в фоне (Python)
4. Регламентные задания с расписанием от 1 мс
5. Всплывающие сообщения
6. Уведомления из любого контекста простые
7. Уведомления с ответом (для Anroid начиная с Oreo)
8. Поле ввода с событием на каждый символ
9. Поле ввода с автозаполнением (предварительно передается список)
10. Новый настраиваемый диалог ввода и работа с ответами диалога
11. Работа с речью и голосом из любого контекста
А также изменения в документации. В данную статью не вошло описание системы группового администрирования и мониторинга.
24
Вопросы:
Для чего копировать базу SQLite на локальные устройства, когда ее можно держать в централизованном облаке? Если скорость доступности не устраивает, то может быть в локальной сети держать?
Основное требование – возможность работы в режиме офлайн. Если требований к офлайну нет, то и нет нужды использовать мобильную платформу, а можно использовать мобильный клиент и тогда не надо держать нигде базу.
У нас появляется требование к офлайну, причем к такому офлайну, где у пользователя может не быть связи полдня, пока он грузит машины. Когда ты полдня в офлайне находишься, то появляется необходимость держать не общую базу, а передавать на каждое устройство. Вот откуда рождаются эти проблемы, они связаны с тем, что нужно обеспечить офлайн.
Мы тоже работаем с маркировкой и логически приходим все к тому, что нужен онлайн. Это проблема не программистов, а системных администраторов в том, чтобы повесить соответствующие точки доступа. Мы не можем хранить маркировки на локальных устройствах. Это очень дорогое и ненужное решение.
Если можно обеспечить точки доступа, то это правильное предложение. Но оно не работает в случае, когда у вас завод в Омске и в Ярославле. Предприятие большое и стоимость бесшовного вайфая на этом предприятии, которое по площади несколько десятков квадратных километров, огромная. Мы просчитывали стоимость в Ярославле, где завод меньше по площади и поближе к цивилизации, чем в Омске, стоимость связи – космическая.
Второй пример, когда для маркировки нужен офлайн, – это где-нибудь на Дальнем Востоке , где 600 километров до цивилизации, и интернет встречается только изредка, и то через GSM. Там невозможно обеспечить достаточную скорость соединения и стабильность, чтобы обеспечить работу в тонком клиенте или в других онлайн-сервисах. Там связь может пропасть на день и даже не доедешь никуда, чтобы подключиться.
По нашему опыту, офлайн требовался на больших предприятиях и на удаленных предприятиях. А во всех других случаях, где можно обеспечить покрытие интернетом, онлайн-решение, конечно, лучше.
У вас большая команда разработки, которая все это делает и поддерживает?
Всего семь человек, из них штатных программистов – три человека. Плюс мы привлекаем дополнительных разработчиков на проект.
Почему мобильный клиент с автономным режимом вам не подошел?
В нашем случае он ничего не решал. Его можно использовать, если автономная работа нужна изредка. Если у вас 50 на 50, вам все равно придется сделать для офлайн-работы отдельные формы, добавить все метаданные и обеспечить обмен. Вам же все равно нужно будет хранить на устройстве все данные, которые нужны для офлайн-работы.
Зато не нужен зоопарк всех дополнительных систем.
А как вы эти данные, которые нужны для офлайн-работы, передадите на устройства? Вам же нужно их передать.
Но если не использовать автономный мобильный клиент, нужно поддерживать одну систему, а в вашем случае – две.
Это не проблема. Поскольку режим автономной работы заставляет нас написать этот обмен даже для автономного мобильного клиента, код мы напишем ровно такой же.
Услышал, что вы бились за скорость передачи и за объем передаваемых данных. Зачем тогда использовался JSON, хоть и порезанный? Почему не использовали бинарный протокол? Зачем вы для хранения GUID и штрих-кодов выбрали регистр, а не справочник?
Бинарный протокол даст в полтора раза выигрыша, но, как правило, у нас передаются одинарные сообщения. Они небольшие и сжимать их особо нет смысла. Там у нас utf-8, где один байт на один символ. Ничего, кроме запятых, из лишних данных там нет.
Бинарный протокол по объему даст выигрыш, но тут мы можем просто в консоли RabbitMQ посмотреть, что происходит. А для бинарного протокола нужно отдельные средства выдумывать. Возможно, мы в будущем перейдем на бинарный протокол, но пока выигрыш не особо чувствуется, и сейчас удобнее расследовать разные проблемы.
Что касается регистра сведений для хранения штрихкодов – это пережиток прошлого. Когда-то мы пытались сделать в MDT такую же структуру метаданных, как в УТ, чтобы было проще разрабатывать и обмениваться. Но столкнулись с тем, что эта структура данных нерациональна, занимает много места и с ней сложно работать. Кое-где мы выпилили ее, но данный конкретный регистр не убрали. Он просто унаследован из типовых решений 1С.
*************
Данная статья написана по итогам доклада (видео), прочитанного на конференции Infostart Event 2021 Post-Apocalypse.
Больше статей можно прочитать здесь.
Итог Архитектуры 1.0 и предпосылки перехода на Архитектуру 2.0
С такой архитектурой проект на «Кордианте» удалось запустить на 100 ТСД.
Все это используется уже полгода без особых проблем, за прошедшее время количество ТСД увеличилось на 20 штук. Инициализация одного ТСД занимает 20 минут.
ERP за этот период уже несколько раз обновлялось – с особыми сложностями мы за это время не столкнулись.
Но все равно проблемы есть.
Первая проблема связана с архитектурой:
-
При работе с большими документами, в которых несколько тысяч строк наблюдаются тормоза – они связаны с записью в одну и ту же табличку при обмене и при текущей работе;
-
Процесс обновления мобильного приложения все равно сложный, он фактически ручной. Отделу ИТ нужно пойти, собрать ТСД, принести в комнату и два QR-кода просканировать. Этот процесс не может быть выполнен обычными кладовщиками.
Есть еще несколько проблем, связанных самим коробочным решением БИТ.MDT и его внедрением на массовом рынке:
-
В текущей архитектуре для работы БИТ.MDT требуются сторонние инструменты – RabbitMQ и вебсервер. Простые пользователи не могут это установить и настроить самостоятельно, для них это слишком сложно.
-
Мобильная часть обновляется вручную, что неудобно.
-
Особенность у маленьких клиентов – при длительном отсутствии связи, например, на пару дней, скапливается много сообщений и ТСД их может разбирать часами. С этим тоже нужно как-то бороться.
В результате мы перешли к архитектуре 2.0, в которой есть незначительные доработки.
Мы поддержали обмен через облачные CloudAMQP и добавили использование SSL – если кто-то следит за нашей десктопной компонентой PinkRabbitMQ, там тоже в связи с этим добавился SSL.
Вместо Web-сервиса для передачи больших данных мы теперь умеем использовать S3 – либо от Amazon, либо от YandexCloud – неважно, где.
Теперь для обычных пользователей никакого дополнительного ПО ставить не надо – мы в рамках подписки даем доступ к отдельному хосту RabbitMQ и к отдельному бакету в S3. Ничего настраивать не надо – человек купил лицензию, ввел два параметра и сразу может обмениваться через облако, лишь бы у ТСД было соединение с интернетом.
Для крупных предприятий оставили старый вариант, когда все хостится у себя.
Более значительные изменения коснулись внутренней архитектуры. У нас появилось отдельное приложение DataProvider, которое отвечает за обмен, хранение и обновление БИТ.MDT снаружи.
Это обычное приложение на андроид, которое работает как служба, и находится между внешними сервисами и мобильным приложением.
Расскажу о DataProvider подробнее.