Содержание:
- Пользовательская история
- Критерии оценки вариантов
- Событийная модель и RMQ
- Маршрутизация в RMQ
- Принцип работы БСП по обработке сообщений в формате Enterprise Data
- Моделирование
- Механизм оповещения об ошибках
- Коллективная работа с КД3 и с универсальным форматом
- Механизм автотестирования
- Итоги проекта
- Полезные ссылки
Пользовательская история
Зайдя на проект, мы услышали следующую историю:
Исходное состояние:
Сложный ландшафт производственной компании, состоящий из нескольких территориально-распределенных систем на базе 1С:УПП, одну из которых планируется заменить на 1С:ERP в качестве основного результата проекта. Параллельно с ERP планируется внедрить новую версию PLM взамен старой. Кроме УПП есть другие 1С-системы: MDM, WMS, ТОИР и ЗУП2.5, которые по возможности надо оставить без изменений. Система MDM является основным, но не единственным поставщиком НСИ: например, физические лица рождаются в ЗУПе, полуфабрикаты в PLM, договоры в ERP. Между всеми системами действует обмен типа точка-точка, написанный на "1С:Конвертация данных 2.0", транспорт — XML-файлы через общие папки. Все конфигурации сильно кастомизированы.
Требования к результатам проекта в части интеграции:
— сократить время синхронизации данных между системами с 15-60 минут до нескольких секунд
— систематизировать и сделать прозрачной разработку и хранение правил обмена, чтобы облегчить работу службы поддержки и минимизировать трудозатраты разработчиков в будущем при добавлении в обмен новых объектов или даже новых информационных систем
— по факту возникновения ошибок обмена уведомлять систему Help Desk о каждом недоставленном объекте. После устранения причин сбоя недоставленные объекты должны быть переотправлены автоматически, чтобы исключить любые потери
— новый релиз правил обмена должен предварительно проходить автоматическое регрессионное тестирование, чтобы гарантировать целостность работающих правил
— применение нового релиза правил обмена не должно вынуждать пользователей переподключаться к системе
— в качестве потенциальных решений транспортного механизма рассматриваются:
— web-сервисы,
— Axelot Datareon ESB
— БИТ:Адаптер, в котором используется внешняя компонента YellowRabbitMQ для работы с RabbitMQ от "Серебряной пули".
— времени на принятие концепции и ее реализацию — 5 месяцев
ОК, прежде чем генерить идеи, команда сформулировала:
Критерии оценки вариантов
— Тестируемость
— Скорость
— Оптимальность потоков
— Независимость от обновления
— Трудоёмкость
— Централизация правил обменов (унификация)
— Поддержка событийной модели
Мы отлично понимали две вещи:
1. Действующие правила на КД2 представляют большую ценность, неплохо бы их сохранить или максимально использовать. С одной стороны они учитывают нюансы всех доработанных конфигураций, в них заложено много человеко-часов. Но с другой стороны правила эволюционировали вместе с конфигурациями в течении 5 лет, писались разными людьми, одна волна накладывалась на другую, накопилось много противоречий и костылей, поэтому оптимальность кода скорее всего низкая.
2. Кроме того на выходе проекта одна УПП должна быть заменена на ERP, а ERP обменивается со всеми остальными системами, значит придется переписать все правила как минимум в части загрузки-выгрузки на стороне ERP.
Далее идут варианты решений, вынесенные на обсуждение, в самом конце будет победитель:
Вариант №1. Вариант с Datareon сразу не прошел ни по срокам, ни по бюджету. Когда знакомишься с такими предложениями, на ум приходит треугольник качества имени Артемия Лебедева: "Долго, дорого, ах…нно!". Интересно, но не в этот раз, возможно когда интеграция будет единственным результатом проекта.
Вариант №2. Во всех информационных системах обновить версию БСП до последней, в которой появились web-сервисы в качестве транспорта для синхронизации данных, и продолжить использование существующие правила КД2. В принципе идея неплохая, учитывая, что 1С в последних версиях платформы 8.3 потрудился над кешированием открытия WS-сессий и заставил их работать реально быстро. Но в нашем проекте мы имели пять ИБ под 8.2, две из которых аж с уровнем совместимости 8.2.13, повышать который еще то развлечение. Следуя древнему принципу "работает — не трогай", мы решили не ворошить мамонтов.
Вариант №3. Создать 1С-базу в роли посредника обмена (аналог шины данных), архитектура данных которой будет похожа на заменяемую УПП и содержать объекты с максимальным количеством реквизитов, участвующих во всём обмене. Правила для обмена будут создаваться в КД2. Потоки данных будут входить в нее и расходиться в соответствии с правилами маршрутизации, заложенными внутри нее. Т.е. базам-отправителям необязательно знать обо всех получателях, их задача передать данные в одну эту базу. Плюсы: больше половины существующих правил КД2 удастся сохранить и использовать. Минусы: оперативность доставки будет недостаточная, потому что файл сообщения КД2 несет в себе схему данных и правила всех преобразований на стороне Получателя, а в рамках событийной модели каждый объект будет отправляться отдельным сообщением, даже если использовать web-сервисы или RMQ, каждое сообщение будет перегружено лишней информацией и накладные расходы на доставку будут чувствительны. Кроме того, еще одна 1С-база будет отжирать серверные ресурсы.
Вариант №4. Сымитировать в конфигурации КД2 концепцию КД3. Если представить универсальный формат Enterprise Data в виде реально существующей конфигурации и написать пару правил Источник->ED и ED->Получатель, при этом программные преобразования на стороне ED как получателя и отправителя свести к нулю, то для каждого направления обмена можно сложить, как из мозаики свой набор правил. Например, можно написать правила для MDM-ED, ED-ERP, ED-УПП, а на выходе получить скомпонованные правила для MDM-ERP и MDM-УПП. Конечно потребуется доработка КД2. Этот вариант по плюсам схож с №3, но в нем нет главного минуса — базы посредника, значит обмен будет идти быстрее. Но все равно недостаточно быстро из-за КД2-сообщения, перегруженного служебными данными.
Вариант №5. Реализовать концепцию, предлагаемую БИТ:Адаптером — база-отправитель является источником XSD-схемы данных, преобразования при отправке практически минимальны, основное преобразование происходит непосредственно на стороне получателей. Эта модель победила во всех номинациях, кроме "Унификация" и "Централизация". Мы увидели в ней много низкоуровневого кода — как потенциального источника ошибок и непрозрачности. Роль разработчиков выходит на первый план. Но концепция действительно рабочая в тех проектах, где нет строгих требований к централизации, и количество объектов обмена и сложность их преобразований невысокая. По мнению БИТа, она является эволюционной с точки зрения развития интеграционного контура предприятия: встраивание новых информационных систем происходит в основном силами разработчиков, ответственных за новые системы.
Вариант №6. Идея универсального формата и КД3 была принята большинством голосов. Как ни странно, она тоже является эволюционной при определенных обстоятельствах. Нет, когда в интеграционном контуре всего две-три информационные базы с сильно непохожими конфигурациями, кажется избыточным выполнение двойной работы по написанию правил выгрузки из источника в универсальный формат и из универсального формата в получателя. Но когда у каждой из трех непохожих баз есть очень похожие родственники, как в нашем случае два семейства: пять УПП-образных баз, две ERP-образных, и одиноко стоящий ЗУП2.5 по сути осколок УПП; и когда из любой базы данные могут передаваться в любые другие базы, идея с универсальным форматом уже не кажется дикой, напротив вполне рабочей. Ведь по сути типовые конфигурации 1С делятся на старые и новые архитектурные поколения, если в информационном ландшафте организации присутствует оба поколения, и для обоих написаны правила преобразования к универсальному формату, то никаких сюрпризов больше не будет. Отраслевые решения, такие как Axelot:WMS или Appius:PLM вынуждены архитектурно подстраиваются под современные типовые конфигурации. А если в ландшафт зайдет не 1С-система, типа SAP, никто не мешает договориться с сапёрами использовать существующий универсальный формат, или если сапёры упрутся, инкапсулировать их формат в существующий универсальный формат. Выбирая вариант №6, мы сознательно отказываемся от тяжёлого наследия КД2-правил и переходим к полноценным КД3-правилам. Конечно мы будем использовать код из старых правил КД2, и конечно мы будем подглядывать в типовые правила КД3. И мы сознательно идем на реформацию старых правил, т.к. это часть требований проекта.
Итоговый подсчет очков по 5-бальной шкале:
Все шесть вариантов были про концепцию правил обмена. Время поговорить про обмен в режиме on-line, событийную модель и способы доставки сообщений.
Событийная модель и RMQ
Тут всё просто. Событийная модель позволяет забыть про планы обмена и связанные с ними пакетные выгрузки. Проще говоря, больше нет необходимости накапливать ссылки на измененные объекты, а потом в условленный час отправлять большую телегу, в которую попадают только последние версии объектов. Теперь мы можем отдавать миру объект атомарно, столько раз, сколько успешно завершилась транзакция при его изменении. При этом отправитель не обязан ждать подтверждения доставки, его миссия закончилась, когда сообщение ушло за его пределы. За доставку и обработку сообщений отвечают другие системы. Безошибочная доставка и обработка сообщений — это нормальное поведение интеграционного контура, не надо тратить ресурсы на уведомление об этом. Извещать отправителя надо только в случае ненормального поведения.
Считается, что основная ценность событийной модели — не столько в оперативности доставки, сколько в соблюдении хронологии событий. У типичного брокера сообщений типа RabbitMQ три главные задачи: быстро получать сообщения из разных источников, быстро перенаправлять сообщения в одну или несколько очередей согласно правилам маршрутизации, и обеспечивать быстрое чтение очередей по методу FIFO. Фишка RMQ еще и в том, что он принципиально не хранит прочитанные сообщения, что делает его слегка безалаберным, но в то же время не слишком требовательным к файловым ресурсам, что радует.
Собственно чтение очереди по FIFO и даёт гарантию соблюдения хроники. Это ключевая функция RMQ, которая гарантирует правильное соблюдение цепочки бизнес-процессов на стороне получателя. Например, сначала должен появиться договор, а затем проведен инвойс по этому договору. Но бывают ситуации, когда допускается несоблюдение последовательности действий, если это не влияет на бизнес. Например, многие типовые конфигурации в пределах одной транзакции сначала создают подчиненный элемент, а потом самого владельца. С точки зрения событийной модели — это два разных события, которые будут воспроизведены на стороне получателя в такой же последовательности, и подчиненный элемент поживет какое-то время с битой ссылкой на владельца. Если это не повлияло на проведение документов, то бизнес ничего не заметит и все будут счастливы. Но если доставка новой номенклатуры задержалась на 15 минут или вообще остановилась, а через 15 минут начали поступать накладные с этой номенклатурой и их проведение остановились, то бизнес это почувствует и встанет на дыбы. Поэтому событийная модель должна быть обогащена системой приоритизации ошибок. Если упаковка прилетела без номенклатуры, мы позволяем ее записать с битой ссылкой и не считаем за ошибку. Если накладная прилетела без номенклатуры, то считаем это ошибкой и фиксируем ее в Help Desk как критический инцидент.
Маршрутизация в RMQ
Немного про маршрутизацию сообщений в RMQ. Сообщение RMQ состоит из шапки (Header) и доставляемых данных (Payload). В Header есть свойства:
Exchange — точка обмена, в нее отправители передают сообщения. Exchange бывают разных типов по способам маршрутизации. Мы использовали тип topic. Exchange хранит правила маршрутизации (Bindings), в соответствии с Bindings RMQ перенаправляет сообщение в очереди (Queues)
Routing Key — ключ маршрутизации
Properties — произвольный набор служебных параметров, которые помимо самого XML-объекта мы хотим показать получателям
Например, мы хотим, чтобы сообщение с XML-образом нового элемента номенклатуры было доставлено из MDM в PLM и ERP. Создаем в RMQ:
— две очереди Data_PLM и Data_ERP
— точку обмена Data
— в точке обмена Data создаем правила маршрутизации:
— Если Routing Key содержит #.PLM.# — перенаправлять в очередь Data_PLM
— Если Routing Key содержит #.ERP.# — перенаправлять в очередь Data_ERP
Здесь точка — это разделитель между словами, решётка — это маска для любого количества произвольных символов.
Теперь если мы из MDM отправим в RMQ сообщение, в котором Exchange = Data и Routing Key = .PLM.ERP., то RMQ переправит такое сообщение в две очереди Data_PLM и Data_ERP. Т.е. за формирование строки Routing Key отвечает база-источник, а за выполнение самой маршрутизации отвечает RMQ, при этом из базы источника в RMQ отправляется всего одно сообщение, а размножение этого сообщения на нужное количество сообщений и помещение их в очереди происходит в RMQ.
Разумеется Exchanges, Bindings и Queues в RMQ надо создать заранее, перед началом обмена.
Более подробно про маршрутизацию RMQ можно почитать тут или найти описание протокола AMQP, он реализован не только в RMQ.
RabbitMQ является свободным программным обеспечением, мануал по установке на CentOS тут. За внешнюю компоненту конечно придется заплатить. Мануал ВК YellowRabbitMQ можно почитать тут. Форум Пули про YellowRabbitMQ тут. При покупке компоненты вам подскажут адрес облака. Но не спешите делать выводы о производительности, у бесплатного сервиса ограничена пропускная способность, лучше заведите Кролика в своей локальной сети. У него достаточно скромные аппетиты к железу, мы использовали такую машину: vCPU (Core) / vRAM Gb / vSSD Total Gb — 2 / 4 / 100.
Принцип работы БСП по обработке сообщений в формате Enterprise Data
Первый релиз КД3 вышел 30.04.2024, в том же году в БСП 2.2 в подсистеме "ОбменДанными" появилась возможность обрабатывать сообщения через универсальный формат. Технология достаточно старая, 1С не собирается от нее отказываться и активно развивает, выпуская готовые правила для большинства современных типовых конфигураций, доведя количество релизов ED до шести.
КД3 обновляется не так часто, как хотелось бы. Последний релиз датируется 27.04.17, и там есть что дорабатывать. Но то что уже есть вполне пригодно, в том числе для коллективной разработки. Сердце КД3 — генератор кода — очень удобная фича: в визуальном конструкторе КД3 можно просто накликать передаваемые свойства и тут же получить модуль с кодом, что само по себе уменьшает трудозатраты и вероятность появления ошибок. Наполнение и отладку обработчиков "При отправке", "При конвертации данных XDTO", "Перед записью полученных данных" можно продолжить уже в целевой конфигурации. Модуль с кодом правил в типовых конфигурациях называется МенеджерОбменаЧерезУниверсальныйФормат. Кто помнит танцы с бубнами для отладки правил КД2, тот возрадуется!
Модуль БСП, формирующий XML-сообщение из выборки данных и получающий данные из XML-сообщения, называется ОбменДаннымиXDTOСервер. Описание универсального формата хранится в типовых конфигурациях в XDTO-пакетах с именами типа EnterpriseData_1_X. Мы возьмем за основу версию 1.5, т.к. на момент проекта она была последней.
Формат сообщения хранится в XDTO-пакете ExchangeMessage. Сообщение в универсальном формате имеет такую же структуру, как и в RMQ: шапка Header и тело сообщения Body. Body не является частью какого либо формата, это искусственный XML-элемент, поэтому оставим его для эстетики. Шапку для RMQ будем формировать сами, поэтому от ExchangeMessage надо избавляться. Но ExchangeMessage хранит в себе тип значения Ref, который используется как базовый тип в EnterpriseData, а в модуле ОбменДаннымиXDTOСервер используется в функции ЭтоСсылкаXDTO(). Значит тип Ref надо перенести в EnterpriseData, переписать ссылки на него, и доработать функцию ЭтоСсылкаXDTO().
Конечно это не единственная доработка модуля ОбменДаннымиXDTOСервер и XDTO-схемы EnterpriseData. Нам предстоит сделать обособленную подсистему, со своими префиксами имен объектов конфигурации и своим URI пространства имен, чтобы они не пересекались с типовыми, когда будем встраивать их в целевые конфигурации информационных баз, участвующих в обмене.
Как вы понимаете, мы собираемся разрабатывать свой универсальный формат, а EnterpriseData_1_5 возьмем в качестве отправной точки. Согласно условиям проекта мы должны применять новые версии правил бесшовно, не изменяя конфигурации и не прерывая сессии пользователей, поэтому хранить XSD-схему формата и модуль менеджера обмена будем в виде бинарных данных в служебных справочниках, которые будем быстро обновлять непосредственно из КД3 по мере выпуска новых версий формата и правил, используя свой же механизм синхронизации.
Модуль с кодом правил будем хранить в модуле внешней обработки, файл которой будем компоновать автоматически из КД3, запуская конфигуратор в пакетном режиме с параметром LoadExternalDataProcessorOrReportFromFiles.
Впрочем, обо всем по порядку.
Моделирование
Выше мы приняли решение применять концепцию событийной модели, формировать правила обмена в КД3, использовать универсальный формат ED, доставлять сообщения через RabbitMQ, оповещать базы-отправители только об ошибках. Опишем поведенческую модель механизма обмена. По нашей практике моделирование позволяет увидеть и учесть все нюансы прежде чем приступать к выработке архитектурного решения.
Шаг №1 "Регистрация"
При записи объекта данных на стороне отправителя:
Шаг 1.1. Определяем, участвует ли объект метаданных в обмене
Шаг 1.2. Определяем наличие изменений в сравнении с последней версией объекта. Это опциональная фича — защита от повторной передачи одинаковых данных с целью экономии трафика. В КД2 это называлось "Фильтр выборочной регистрации объектов". Это не просто сравнение двух XML-текстов, полученных методом СериализаторXDTO.ЗаписатьXML. Правильно сравнивать только те реквизиты, которые участвуют в обмене. Ну или хотя бы исключить общие реквизиты, типа "Дата изменения", опять же если они не участвуют в обмене.
Шаг 1.3. На основании правил регистрации данных определяем, каким получателям этот объект должен быть доставлен, и формируем строку Routing Key. Правила регистрации хранятся в РС "Получатели данных". Сами правила — это произвольный текст с кодом, или другими словами "Модуль отбора", цель которого — определить булево значение переменной "Отказ". В каждой базе-отправителе, для каждого типа данных, участвующего в обмене, для каждого получателя этого типа данных надо создать отдельную запись РС "Получатели данных". Если в каком-то направлении при определенных условиях данные не должны передаваться — тогда пишем код для этого условия в модуле отбора.
Шаг 1.4. Определяем последнюю версии формата и модуля менеджера обмена. Зачем вообще версионировать формат и менеджер обмена? Допустим мы обновили версию формата одновременно во всех базах, но в очередях остались непрочитанные сообщения, сформированные с помощью предыдущей версии формата. Значит получатели должны иметь доступ ко всем предыдущим версиям формата и к последней версии менеджера каждой версии формата. Кроме того на случай отказа последней версии менеджера (если модуль не проходит проверку при компиляции из-за малейшей синтаксической ошибки — останавливается работа всех правил!) мы всегда должны иметь возможность откатиться на предыдущую стабильно работающую версию менеджера, хотя бы для передачи служебных данных (тех же версий форматов и менеджеров). В идеале мы конечно исключаем вероятность помещения в продуктив не протестированных версий, но разработчики в тестовом контуре должны иметь право на ошибку.
Шаг 1.5. С помощью доработанного модуля ОбменДаннымиXDTOСервер формируем текст XML-сообщения в формате Enterprise Data.
Шаг 1.6. Формируем параметры сообщения:
— Exchange ID: это обязательный параметр, он указывает RMQ какая точка обмена будет обрабатывать сообщение. У каждой точки обмена свой набор правил маршрутизации. Наличие разных точек обмена расширяет возможности маршрутизации. Мы создали три точки обмена: XSD (для версий форматов и менеджеров обмена), DATA (для пользовательских данных) и LOG (для РС "Состояния сообщений" и "Ошибки обмена"). Сообщение с Exchange = XSD и RoutingKey = .ERP.PLM., будет переправлено в очереди XSD_ERP м XSD_PLM. Сообщение c Exchange = DATA и RoutingKey = .ERP.PLM. будет переправлено в очереди DATA_ERP и DATA_PLM. Хотя обе очереди XSD_ERP и DATA_ERP читает одна база ERP, приоритет обработки у них разный. Служебные данные надо доставлять в первую очередь. Получатели должны сначала выбрать все сообщения из очереди XSD, и только после этого приступить к очереди DATA.
— идентификатор сообщения (Message ID): для облегчения отслеживания маршрута сообщения при разборе полетов
— системное время события — время в миллисекундах завершения транзакции для соблюдения событийной модели (результат функции ТекущаяУниверсальнаяДатаВМиллисекундах)
— сценарий обработки на стороне получателя: здесь может быть раздолье для творчества. Например, сколько раз делать попытку записи при конфликте блокировок транзакций, или что делать с документом, если он проводится с ошибкой, или снимать ли контроль при записи (ОбменДанными.Загрузка = Истина)
— указатель на объект данных: сериализованный в XML однозначный идентификатор объекта данных, пригодится при разборе сбойных ситуаций, в частности для повторной отправки недоставленных сообщений. Для ссылочных типов — это пара "тип метаданных" и GUID ссылки, для регистров сведений — набор измерений.
— HASH указателя на объект данных: его будем использовать на этапе записи объекта на стороне получателя: на случай если один и тот же объект передаётся в коротком интервале времени — будем использовать последовательную, а не параллельную обработку сообщений, но об этом чуть ниже. Сам HASH будет иметь тип УникальныйИдентификатор, полученный из предыдущего параметра (указатель на объект данных) по алгоритму MD5. Для совместимости с 8.2 алгоритм MD5 придётся брать из Windows, а не из платформы 1С, платформа .NET Framework обязательно должна стоять на машине с сервером 1С, чтобы обеспечить вызов COM-объектов:
Crypt = Новый COMОбъект("System.Security.Cryptography.MD5CryptoServiceProvider");
Text = Новый COMОбъект("System.Text.UTF8Encoding");
Шаг 1.7. Записываем полученное сообщение в регистре "Лог недоставленных сообщений"
Шаг 1.8. Записываем событие "Зарегистрирован" в регистр "Состояния сообщений"
Все механизмы шага №1 должны выполняться с максимальной скоростью, и защищены от каких либо падений по ошибкам, так как происходят на глазах у пользователя внутри транзакции записи данных. Нам удалось добиться длительности выполнения шага "Регистрация" не более 0,4 сек.
Шаг №2 "Отправка"
Шаг 2.1. Регламентное задание "Отправить сообщения в RMQ" отправляет в RMQ сообщения, накопившиеся в РС "Очередь недоставленных сообщений". После успешной отправки сообщения в RMQ запись из РС удаляется. Периодичность регл задания мы выбрали эмпирическим путём: каждые три секунды. Регл задание должно иметь уникальный ключ, чтобы исключить параллельное выполнение, что при такой частоте запуска не исключено. Результат запроса должен быть отсортирован по реквизиту СистемноеВремяСобытия, чтобы соблюсти событийную модель.
Выполнение запроса к РС надо выполнять внутри программной транзакции, чтобы исключить грязное чтение, т.к. запись в РС происходит внутри транзакций записи объекта данных, значит есть вероятность отката транзакции. Согласно теории, на объекты, записанные внутри транзакции накладывается блокировка типа X, которая запрещает другим транзакциям накладывать на этот объект любые другие блокировки. А при чтении внутри транзакции на объекты накладывается блокировка типа S. Значит запрос внутри транзакции ко всей таблице РС выполнится тогда, когда завершатся все начатые до этого транзакции, что и защищает от грязного чтения. Если база данных SQL переведена в режим READ COMMITTED SNAPSHOT, то будет еще проще — запрос в транзакции всегда будет возвращать записи только завершенных транзакций и не будет зависать на блокировках.
Почему нельзя было отправить сообщение на шаге "Регистрация" и тем самым ускорить процесс обмена? Честно говоря мы испугались оптимистичного сценария: что транзакция записи объекта данных после отправки не будет прервана, и что не будет коммуникационных проблем с сервером RMQ. Разработчики 1С-платформы не гарантируют очередности выполнения подписок на события в порядке следования в конфигураторе. Но даже если это и так, нет гарантии, что в будущем какой-то внедренец не вставит в конец списка свою подписку и она не будет прерывать транзакцию. Что касается коммуникационных проблем — как показала практика сам Кролик работает стабильно, и сообщения уходят быстро, потому что мы не передавали тяжелые бинарные данные, и вообще старались не помещать в сообщение больше одного объекта. Но опять же нет гарантии что в будущем не найдется внедренец, который нарушит эти правила.
Шаг 2.2.— записываем событие "Отправлен" в регистр "Состояния сообщений"
При желании передачи записей регистра "Состояния сообщений" в отдельную базу с целью логирования — можно рассматривать этот регистр как объект обмена (на диаграмме отправки он закольцован на вход алгоритма), но тут главное вовремя прервать бесконечную рекурсию — отключить запись состояний "Зарегистрирован" и "Отправлен" при передаче самого регистра "Состояния сообщений"!
Шаг №3. "Доставка"
Шаг 3.1. На стороне получателя регламентное задание "Получить сообщение от RMQ" читает содержимое очередей RMQ и записывает их в РС "Лог состояний сообщений" со статусом "Доставлен". РС хранит не только статус сообщений, но и содержимое, чтобы на следующем шаге можно было их преобразовать из универсального формата в объект получателя и записать.
Имена очередей и их приоритетность хранится в справочнике "Источники данных". Сначала выбираем все сообщения из очереди с приоритетом 0. После этого читаем одно сообщение из очереди с приоритетом 1, возвращаемся к нулевой очереди и так далее. Почему так? Через очередь XSD мы передаем служебные данные (версии форматов и версии менеджеров обмена), их мы должны получить как можно быстрее и быть во всеоружии, т.к. в очереди DATA могут быть сообщения с обновленной версией формата.
Периодичность регл задания мы выбрали эмпирическим путем: каждые три секунды. Регл задание должно иметь уникальный ключ, чтобы исключить параллельное выполнение, что при такой частоте запуска не исключено.
Регламентное задание "Получить сообщение от RMQ" в циклах чтения сообщений проверяет работу фонового задания следующего шага "Обработать доставленные сообщения". Если оно не запущено, то запускает его. Это позволяет не прерывая процесса получения сообщений приступить к их обработке.
Шаг №4. "Запись"
Шаг 4.1. Фоновое задание "Обработать доставленные сообщения" читает из РС "Лог состояний сообщений" необработанные сообщения, разумеется в порядке системного времени события, полученного на шаге 1.6.
Шаг 4.2. Для каждого сообщения запускается отдельное фоновое задание "Обработать доставленное сообщение", которое производит преобразование и запись объекта, а так же снимает признак "Не обработано" с полученных сообщений и записывает в РС состояние "Записан".
Фоновое задание "Обработать доставленные сообщения" выполняет две важные функции:
— регулирует максимальное количество одновременно запущенных заданий "Обработать доставленное сообщение"
— выстраивает сообщения с одинаковым HASH указателя на объект данных (полученного в шаге 1.6) в последовательную цепочку, чтобы не получить взаимных блокировок.
Для чего нужны все эти сложности с параллельностью обработки полученных сообщений? Для производительности. Шаг Записи из всех четырех шагов (Регистрация, Отправка, Доставка, Запись) самый медленный, а быстродействие всего механизма обмена определяется суммой всех шагов.
Опытным путем мы установили оптимальное число фоновых заданий — пять. Это то число, которое в реалиях заказчика обеспечивало скорость доставки в среднем 4 секунды, и в то же время не мешало работе пользователей на стороне получателя. При 50 параллельных заданиях пару раз в день мы наблюдали картину, как вся база вставала колом. Изоляция фоновых заданий в отдельные рабочие процессы на сервере 1С не сильно помогала. Причем это была именно деградация производительности сервера, а не эскалация блокировок.
Так же 5 параллельных заданий обработки полученных сообщений не сильно удаляют нас от событийной модели. Если мы и нарушаем хронологию, то в пределах разницы времени записи самого быстрого и самого медленного объекта.
Механизм оповещения об ошибках
На тему ошибок есть две важные установки:
- Вовремя исправленная ошибка не считается ошибкой!
- Правильное отчуждение результата проекта — это когда в возникающих ошибках начинают разбираться не только авторы-разработчики, но и служба поддержки заказчика
Чем точнее сообщение об ошибке, тем быстрее она будет исправлена, поэтому мы в течении всего проекта пополняли базу знаний об ошибках и вставляли в код точки оповещения.
Поведенческая модель механизма следующая:
— сообщение об ошибке попадает в РС "Ошибки обмена". У него заполняется три измерения "HASH указателя на объект данных", "ИБ возникновения ошибки", "ИБ источник объекта". Соответственно если ошибка возникает в том же месте, по тому же объекту, то информация о ней актуализируется, а не множится.
— каждый раз при успешном выполнении одного из шагов обмена удаляется запись из РС "Ошибки обмена", если она там есть. Т.е. РС "Ошибки обмена" служит для отображения неисправленных ошибок в текущем моменте. Если ошибка исправлена, то запись о ней удаляется автоматически.
— все записи РС "Ошибки обмена" передаются на сторону ИБ-отправителя. В форме списка РС есть две кнопки: "Переотправить выделенные сообщения" и "Переотправить все сообщения". Поиск объекта для переотправки происходит с помощью реквизита "Указатель на объект данных". Для ссылочных типов — это пара "тип метаданных" и GUID ссылки, для регистров сведений — набор измерений. Таким образом, после устранения причины ошибки у службы поддержки есть возможность одним нажатием переотправить все недоставленные объекты из ИБ-отправителя.
— каждые 15 минут запускается регламентное задание по отправке сообщений о текущих ошибках в Help Desk. Оповещения об ошибках отправляется непосредственно из ИБ возникновения ошибки. В Help Desk по виду объекта и месту возникновения определяется уровень критичности ошибки.
С какими ошибками мы столкнулись за время проекта:
— Внешняя компонента V8RMQClient вдруг перестала работать, причем метод ПодключитьВнешнююКомпоненту("ОбщийМакет.V8RMQClient", "V8RMQClient", ТипВнешнейКомпоненты.Native) выполняется успешно, но любые другие действия приводят к ошибке "не найден файл внешней компоненты". Выяснилось что айтишники периодически в папках сервера 1С чистят кэш. 1С-платформа само действие по записи файла компоненты из общего макета на диск выполняет лишь раз, а при повторном обращении сразу берет файл с диска. В общем договорились с айтишниками, что они чистку кэша будут совмещают с перезагрузкой сервера 1С и проблема исчезла.
— В самом начале мы забыли про защиту запуска регл заданий от копирования базы, и с удивлением наблюдали, как из очередей стали пропадать сообщения — одну очредь читали разные базы! Сделали стандартный механизм сравнение со строкой подключения ИБ, и заодно сценарий поведения при разоваричивании копии продуктовой базы в тестовом контуре — автоматическое переподключение к другому серверу RMQ и отключение оповещений Help Desk.
— Про периодический ступор базы ERP при 50 параллельных фоновых заданиях обработки полученных сообщений выше уже упоминалось. Шутки пользователей в стиле "Угомоните кролика, дайте поработать" в конце концов заставили снизить это число до 5.
— Это даже не ошибка, а фича. Все наверное уже забыли, что в СУБД платформы 8.2.13 константы хранились в одной таблице в виде одной строки с кучей колонок. И в языке запросов обращение к ним было "Выбрать К.ИмяКонстанты Из Константы КАК К", а не "Выбрать К.Значение Из Константа.ИмяКонстанты КАК К". Мы это "вспоминали" каждый раз, когда обновляли нашу подсистему в конфигурациях 8.2.13. Вообще, написание универсальной подсистемы, совместимой со всеми версиями платформы, начиная с 8.2.13 и выше — сильно взбодрило! Пришлось вспомнить многие хорошо забытые вещи. И все равно в итоге при обновлении каждой конфигурации приходилось идти по внушительному чек-листу, чтобы не забыть учесть все локальные нюансы.
Коллективная работа с КД3 и с универсальным форматом
Большая часть времени проекта была посвящена написанию правил обмена в КД3 и обогащению универсального формата Enterprise Data новыми объектами. Временами количество одновременных разработчиков доходило до 5. Как мы решили проблему коллективной разработки:
— в состав типовой конфигурация КД3 включен план обмена "Рабочие места" с правилами обмена на КД2. Каждому разработчику создали распределенную базу КД3
— так же в составе конфигурация КД3 есть иерархический справочник "Группы правил", он прошивает все правила обработки данных, правила конвертации объектов, правила конвертации предопределенных данных и алгоритмы. В нем мы создали группу "Разработка" и под ним имена разработчиков. Мы договорились, что пока идет разработка и тестирование новых правил, разработчик помещает правила в свою папку. Это служит сигналом для других разработчиков, что правила захвачены и их трогать нельзя.
— доработку XDTO-объекта EnterpriseData каждый разработчик вел в конфигураторе своей базы КД3. Базы КД3 подключены к хранилищу конфигурации. Разработчик захватывает XDTO-пакет, вносит изменения, выгружает пакет в XSD-файл, загружает файл в структуру формата в своей базе КД3, проверяет, помещает XDTO-пакет в хранилище, извещает остальных разработчиков, если были затронуты чужие объекты.
Жизненный путь релиза с правилами в итоге получился такой:
— разработка и тестирование правил в контуре разработчика
— автотестирование релиза правил в тестовом контуре
— разворачивание в продуктивном контуре копии КД3 из тестового контура
— распространение правил из КД3 по информационным базам продуктового контура
Механизм автотестирования
Когда кода становится много, при разработке нового функционала повышается вероятность повреждения функционала смежных подсистем. То же касается разработки правил обмена. Выявлять такие повреждения помогает регрессионное тестирование в тестовом контуре.
Мы разработали справочник "Шаблоны автотестирования" и регламентное задание, которое выполняет на стороне ИБ-отправителей создание и удаление объектов данных по шаблонам. Далее вся информация о результатах обмена стекается в базу анализа результатов автотестирования.
На первом уровне анализа проверяется сам факт передачи объектов в нужных направлениях.
На втором уровне проверяется качество передачи — сравниваем подготовленные заранее XML-эталоны: с XML объекта данных на стороне отправителя, c XML текстом сообщения в формате ED, и с XML объекта данных на стороне получателей.
На скриншоте показан отчет первого уровня анализа. Очевидно, что тест "Штрихкоды" не выполнился, т.к. на стороне получателя была ошибка.
Итоги проекта
- Все исходные требования к результатам проекта в части интеграции были выполнены
- Появился прецедент синтеза двух современных механизмов интеграции — КД3 и RMQ
Другие итоги будем дописывать сюда по мере обсуждения в форуме под публикацией.
Полезные ссылки:
- Описание БИТ:Адаптера: bit-erp.ru/adapter
- Описание механизма маршрутизации Rabbit MQ: www.rabbitmq.com/tutorials/tutorial-five-python.html
- Инструкция по установке Rabbit MQ: www.rabbitmq.com/install-rpm.html
- Описание методов компоненты YellowRabbitMQ: 1c-e.ru/подсистема-интеграции-реального-вре/
- Форум Серебряной пули про YellowRabbitMQ: xdd.silverbulleters.org/c/integracziya/yrabbitmq
Авторы:
Рецензенты:
Парни, вы круты! Очень реально круто!
Спасибо за качественную статью!
Напишите как вы на практике решали вопрос с массовыми изменениями? Скажем если происходит обновление данных в справочниках, достаточно ли эффективен в этом случае подход пообъектной сериализации или для таких случаев лучше выполнять синхронизацию, используя другие технологии?
Интересно будет подробнее прочитать про новые технологии.
Хороший подход, так и надо делать все обмены и рэббит отличная вещь.
Имхо: кд3, куча форматов ed, xdto, xml — это кошмар и тупик. Очень жаль, что 1с идет в этом направлении.
И лично мне не нравится использование com компонент для рэббита и хэша, хотя это простой и легкий путь, но красивее что-то другое придумать.
(5)
Откуда взялась информация о COM компоненте ? Там чистый Native Win32/Win64/GCC32/GCC64
(6) Переведу многонерусскихбукв от Алексея на 1С-овский 🙂
Там нет COM-компонентов, не надо ничего на машине регистрировать/администрировать, плюс это полная кроссплатформенность Windows/Linux 32 и 64 бита.
Кстати, у нас вышло в продажу еще и дополнение для БСП, в котором как раз штатными обменами отправляются сообщения в RabbitMQ. На сайте пока нету, но по телефону можно все узнать. Позволяет быстро получить интеграцию на штатных механизмах типовых 1С-систем. С другой стороны, быстро — не значит правильно, и для сложных гетерогенных проектов, когда есть не только 1С, нужно что-то «посерьезнее».
Я просто поинтересоваться — а как это они у вас так чистят кеш? При работающем сервере, прямо у него из-под носа убирают файлы? Клево, а кто им такое разрешил?
(7)
скажите, пожалуйста, стало очень интересно.
Т.е. получается, что можно взять типовые обмены, например, между УТ11 и Розницей, вашу компоненту, поставить рядом RabbitMQ и все будет обмениваться практически в реальном времени?
Я имею ввиду именно ту ситуацию, когда типового обмена достаточно, когда нет реальной необходимости в полноценном внедрении RabbitMQ вашими силами с учетом всех мыслимых нюансов и вот этим всем.
(0) Добавьте правильную ссылку на компоненту и описание интеграции от Серебряной Пули, пожалуйста.
Аплодирую стоя. Пока такие спецы есть — родина без автоматизации не останется!
(0)
На втором уровне проверяется качество передачи — сравниваем подготовленные заранее XML-эталоны: с XML объекта данных на стороне отправителя, c XML текстом сообщения в формате ED, и с XML объекта данных на стороне получателей.
не совсем понял, зачем и что проверяете.
кролик же гарантирует доставку и качество.
у вас были случаи, когда сообщение доставлено, но частично?
(10)
Там чтобы скачать документацию надо ввести свои данные. ввел пару раз, но так ничего и не пришло. Это может отпугнуть разрабов, слишок коммерческая страничка.
(10)
Там чтобы скачать документацию надо ввести свои данные. Ввел пару раз, но так ничего и не пришло. Слишком коммерческая страничка, это может отпугнуть разрабов, .
(8) Мы не стали интересоваться, просто перевели сервера в другую обслуживающую компанию )
(13) Это я так сделал. Я увидел твои заявки и подумал что ты экспериментируешь с сайтом и их почистил ;-). Поэтому коллеги твоих запросов не увидели ;-).
(12)когда идёт доработка правил одновременно с разработкой конфигурации есть большой шанс что кто то накосячит, например уберет реквизит или целый справочник . Поэтому сравнение итогового сообщения важная штука.
(9) В целом именно так. То есть меняется только транспорт с файлов/web-сервисов
позволяет сделать следующий ход
0. старт
1. взять инфраструктурщиков и попросить у них кластер RMQ
2. поменять транспорт БСП
3. запустить обмен по новому транспорту
4. переписывать обмены не надо — все полетит уже по новому, PROFFIT Номер 1
5. прикинуть где нужен реальный обмен уже с явным использованием событийной интеграции
6. взять бизнес-событие (например «Обновление данных Номенклатуры»)
7. реализовать по новому
8. запустить «Событийную интеграциию для номенклатуры»
9. Запустить уже БЕЗ инфраструктурщиков
10. Proffit Номер 2
То есть получается этакий гибрид штатного обмена и нового.
(8) это прям жестоко получается — серверный кеш при попытке удаления будет ругаться что файл занят. Это надо постараться чтобы так сделать.
(12) Тут речь немного о другом. Мы же проверем новый релиз перед накатом на продуктив.
Качественный анализ автотеста показывает, что с момента создания шаблона что-то произошло именно в контексте этого объекта метаданных — изменились правила, изменился формат, изменилась архитектура. Т.е. заставляет тестировщика сфокусироватья на конкретных изменениях. Если это ошибка — отдать на исправление, если это развитие — актуализировать шаблон.
(21)
1. К обмену через com-соединение много вопросов: по быстродействую, по чуствуительности к обновлению платформы. Не наш вариант.
2. Механизм «Планы обмена» — хорошая штука, у 95% организаций до сих пор работает. А вы пробовали запускать такой обмен каждые три секунды?
3. Если оставаться на планах обмена и правилах КД2 — то да, ничего менять не надо, кроме самих правил. Но тут см п.2
(3) Хороший овпрос! Массовый обмен надо разделить на два случая:
1. Первичный перенос из старой системы в новую — лучше делать на КД2. Все таки накладные расходы на поштучную обработку отнимают ресурсы и время, да и событийность не надо соблюдать
2. Групповая обработка — тут ничего не поделаешь, если изменяется значение реквизита, который участвует в обмене — ничего не поделаешь надо обмениваться. Но:
— Если реквизит не участвует в обмене — от лишнего трафика спасает механизм на шаге 1.2.
— Если реквизит участвует в обмене — время обработки очереди на шаге №4 (Запись) конечно удлинняется. Если такие изменения позарез нужны бизнесу в течение дня и нет возможности перенести на вечер, тогда кратковременно врубаем 50 параллельных фоновых. Так же у нас есть возможность на шаге №2 в пользовательском режиме отключать чтение очереди «в транзакции». Ведь когда он включен — мы ничем не лучше чтения таблиц регистрации планов обмена — тот же эффект ожидания блокировок. Но мы хотя бы можем это параметрически регулировать.
(22)
1) по быстродействию быстрее, только платформа одинаковая должна быть
2) КОМ-обмен будет работать каждые 3 секунды, через XML вряд ли
3) с КОМ-обменом тоже изменять надо только 1 базу
(24)Если есть конкретный проект — опишите, с удовольствием почитаем! Я серьезно!
Интересно было почитать. Не во все тонкости ещё вник. Была подобная задача в 2015-м году. Интеграция стороннего софта для производства с 1С УПП, в перспективе с КА 2, БП 3 и т.п. Поэтому выбрал КД3. По окончании проекта явно прослеживалась необходимость в другом транспорте, но бюджет и сроки не дали развития. Хорошо, что вам удалось разработать концепцию, собрать команду, реализовать и поделиться идеей.
По поводу формирования строки Routing Key. В типовом XDTO пакете ExchangeMessage есть же свойства To и From тип строка. Можно было их использовать? В поле To записать всех адресатов, на стороне приемника перепроверять для него ли это сообщение.
И некоторое время назад появилось свойство AvailableObjectTypes. Может быть это пригодилось бы.
Это свойство с одной стороны увеличило объем сообщения как в КД2 — в каждое сообщение добавляется список поддерживаемых объектов — что может принять база и что может отправить, чтобы не выгружать то, что не может принять другая сторона.
Может быть имело смысл обмениваться этими данными не в каждом сообщении, а при изменении правил. Как это зафиксировать — другой вопрос. Можно по факту перезаписи настроек узла или по таймеру раз в сутки.
Может быть пригодится, в тексте было:
«Разработчики 1С-платформы не гарантируют очередности выполнения подписок на события в порядке следования в конфигураторе. Но даже если это и так, нет гарантии, что в будущем какой-то внедренец не вставит в конец списка свою подписку и она не будет прерывать транзакцию»
Я гарантирую!) Если создать динамическую подписку «ПодключитьОбработчик» — он точно последним сработает.
То есть можно сделать подписку на все объекты на событие «ПередЗаписью», и там на объект подключать динамическую подписку.
Я использовал такую схему, чтобы замерить к примеру проведение документов, чтоб гарантирована замерить все операции и не вставлять замеры во всевозможных местах.
(26) Спасибо за комментарий!
Вы пишите про маршрутизацию — механизм, который указывает, какие типы метаданных из какого источника в какие получатели и при каких условиях должны уходить. В 1С-ской концепции обмена через универсальный формат за маршрутизацию отвечают знаменитые правила регистрации КД2. Ваше предложение я тоже понял: в конечном итоге надо минимизировать доработки типового механизма, как это кстати сделали ребята из Пули, выпустив. недавно дополнение для БСП, в котором штатными обменами отправляются сообщения в RabbitMQ.
Все эти знания в конечном итоге поступают на вход конкретных проектов, и архитектор принимает одно из двух решений:
1. Использовать комбинацию тиражных решений с минимальныи доработками и в дальнейшем мириться с тем что это не до конца вписывается в потребности конкретного бизнеса (кто-то скажет что у него вписалось идеально, но я в сказки не верю, особенно для крупного бизнеса, где каждая деталь имеет значение)
2. Или кастомизировать имеющиеся решения с максимальным учетом особенностей бизнеса.
А теперь скажите, какое из двух решений является более интересным для нас с вами, и является эволюционным с точки зрения развития имеющихся решений или даже появления новых тиражных продуктов? )))
(28) Лично мне интереснее 1-й вариант, т.к. позволяет многократно использовать(продавать) собственные решения за счет максимальной совместимости с тиражными решениями. Проще найти специалиста для поддержки.
2-й вариант на первых порах интереснее бизнесу, дороже, сложнее в долговременной поддержке, т.к. нужны уникальные знания специалистов. И данное решение может отстать в развитии от тиражного, где скорее всего появится что-то интересное для этого бизнеса. Вероятность того что это индивидуальное решение для бизнеса станет тиражным — низкая. А для команды разработчиков и внедренцев этот вариант может оказаться топтанием на месте. Время идёт, деньги платят, собственного развития нет. А конкуренты из варианта 1 за это время уже наработали более совершенный материал для будущего проекта.
(29) согласен полностью, но я немного о другом )
(27) интересно!
А можно чуть подробнее про метод ПодключитьОбработчик или ссылку?
Как в при такой схеме обмена решалась проблема с коллизиями изменения данных?
Из описания механизма обмена следует, что информация о необходимости выгрузки (регистрация изменений) очищалась сразу после выгрузки в брокер. Информация оставалась максимум в логах обмена, которые не анализировались в момент загрузки данных, источником которых является другая база.
Возьмем классическое описание коллизии для такого случая.
1) В базе «А» изменился элемент справочника «Номенклатура».
2) Одновременно с этим в базе «В» изменился тот же элемент справочника.
3) База «А» выгружается свои изменения в RMQ.
4) База «В» выгружается свои изменения в RMQ.
5) В базу «А» приходит элемент из базы «В» и затирает ранее сделанные в базе «А» изменения.
6) В базу «В» приходит элемент из базы «А» и затирает ранее сделанные в базе «В» изменения.
7) Имеем итог: две базы просто обменялись состоянием элементов. Ни в одной из них оно не стало корректным.
Обойти такую ситуацию на первый взгляд можно разрешив изменения номенклатуры только в одной из баз. То есть для каждого типа справочника назначить свою базу, а в остальных запретить изменения в этом справочнике. Но это очень жесткое ограничение, которое например позволяет обойти обмен через «Планы обмена», так как информация о регистрации остаётся до получения квитанции от базы-получателя.
Каждый раз читая про RMQ кажется что коллизии решаются либо через такие запреты, либо есть надежда что за интервал обмена в 1-3 секунды изменения одного и того же элемента не будут выполнены в двух разных базах. То есть коллизии не обрабатываются из расчета на их низкую вероятность.
Обрабатывалась ли такая ситуация в данном случае?
При коллизии есть возможность увидеть, чей вариант в данной базе и когда он возник в источнике?
Спасибо за статью, хотела сказать что лично мы застряли на 4 варианте и даже не представляли что такое возможно.
(32) Да, в теории коллизии возможны, но реальный бизнес мы (автоматизаторы) должны убеждать, что у каждого элемента НСИ или документа должно быть одно место публикации, остальные места — чисто подписчики для чтения. Допускается цепочка дообогащения элементов по базам, но без обработной связи. Иначе будет хаос в информационной системе и в конечном счете в бизнесе .
В данном проекте нам удалось решить коллизию с номенклатурой, которая рождается и в НСИ и в PLM следующим образом:
— выделили разные диапазоны артикулов для новой номенклатуры, заводимой в MDM и в PLM.
— номенклатура, попавшая в PLM из MDM блокируется програмно для изменений
— как только номенклатура, попавшая в MDM из PLM дообогащена, то такая номенклатура в PLM блокируется для изменения
(33) да, там где это нужно, мы сделали специальный РС для ссылочных объектов — указывающий место публикации элемента
(34) Интересно, удалось в итоге внедрить эту схему?
(37) это оказалось вредная идея фикс, из за которой генерация других идей и вариантов был остановлен, а реализация этого требует больше времени, чем прогнозное время поддержки формата ED.
Со временем, думаю кд 3 допилят, добавив в нее то, чего в ней не хватает, например корреляции между конфигурациями и форматом ED.
(38) Вангую, что 1С поймет наконец, что ED надо дать возможность дорабатывать, а не пользоваться суррогатами, типа AdditionalInfo. Может сделают нормальный конструктор. Загрузчик данных из конфигураций. Подключение к хранилищу….
На доработки конфигурации лимит установлен был виндоус, а не 1с. Количество одновременно открытых объектов при объединении конфигураций ограничено.
Следовательно либо групповая разработка одной конфигурации без объединения, либо предельный размер конфигурации в половину от лимита.
(39) универсальный формат ED можно дорабатывать, никто не запрещает и даже КД3 поддерживает. Правда его универсальность пропадёт. Но если в рамках одной организации нужно наладить обмен между зоопарком разных баз, это может быть выходом. Универсальный формат в пределах Вашей организации будет.
(35) Большое спасибо за ответ!
А сам RMQ не содержит средств для анализа таких ситуаций? Всё же хотелось бы, чтобы такого ограничения не было.
Представьте себе ситуацию (пример из реальной практики) когда есть центральная база, например ERP, где контрагент/партнер создаётся через обмен с сайтом или после звонка в кол-центр. Затем этот клиент может прийти в магазин, где идёт работа в другой базе, например УТ или Рознице. Там он уточняет персональные данные, которые уходят обменами в центральную базу. Сразу после покупки он может зайти на сайт с телефона или позвонить в кол-центр и поменять ещё какие-то данные о себе. Например забыл в магазине сообщить новый номер телефона и решил его уточнить. А данные эти идут в центральную базу и затем снова в базу магазина.
При использовании платформенных средств обмена такую ситуацию можно обработать вплоть до объединения реквизитов по каким-то признакам (например если учитывать универсальное время их изменения). Система вплоть до завершения обмена имеет информацию, что объект был изменен и нуждается в синхронизации. Идентификаторы контрагента (или другой НСИ) при этом должны оставаться неизменными, их нет смысла делить по источнику возникновения.
Нет ли при использовании RMQ возможности обработать коллизии программно, а не организационными методами? Например, можно ли при отправке в очередь получить от самого RMQ информацию, что аналогичная информация (например с таким же GUID или заголовком) уже есть в очереди для обработки той базой, которая собиралась отправить её со своей стороны, и перед отправкой должна быть получена и обработана ей?
(39) Ох. Сколько лет уже прошло, но этой возможности не появилось. Кажется что ED изначально создавался и сейчас развивается в основном для обмена с базами регламентированного учета (БП, ЗУП). Раньше даже обмен характеристиками номенклатуры не был полноценно реализован и доработка была не из простых. И чтобы видами номенклатуры обменяться надо было сильно постараться. Сейчас наверное уже доработали.
P.S.: Проверил. Видов номенклатуры по прежнему нет. То есть, например, чтобы отправить из одной базы УТ в другую номенклатуру нового вида по прежнему нужно свой пакет создавать или делать собственную сериализацию и паковать вид в AdditionalInfo. В таких условиях конструктор пакета действительно не помешал бы.
(42) Нет, RMQ это всего лишь быстрый транспорт, не более.
Ситуацию которую вы описали можно попробовать решить так: разделить карточку клиента на две группы одинаковых реквизитов по их автору:
1 группа — реквизиты измененные сотрудниками компании
2 группа — реквизиты измененные самим клиентом
Далее должен быть какой-то механизм принятия одного из вариантов в качестве основного, скорее всего привязанный к какому-то событию — не знаю, личному общению клиента с оператором, либо валидация документов. В любом случае — это задача службы, ответственно за НСИ.
(31) Да проще в синтаксис помощнике почитать, этого хватить должно.
https://its.1c.ru/db/v8314doc#bookmark:dev:TI000000212​ ;
(43) В формате 1.6 виды номенклатуры есть и в ERP 2.4.7 и аналогичных КА, УТ они появились так же как и характеристики, но вариант из коробки опять нерабочий. Нет обмена дополнительными реквизитами характеристик, вид номенклатуры без справочника «Наборы дополнительных реквизитов и сведений».
Пришлось всё переделать в расширении. Но оно не решает все вопросы — пока нельзя изменить состав плана обмена не меняя конфигурации.
Не хватает в ED универсального документа и справочника с универсальной табличной частью, чтобы не меняя формата была возможность обменяться неподдерживаемыми форматом документами и справочниками. Пришлось в качестве универсального справочника использовать статьиДДС и на стороне приемника проверять что это, чтобы подставить нужное ПКО.
(45) А, понял, ДобавитьОбработчик, а не ПодключитьОбработчик. Да, инересно, мы совсем забыли про эту возможность, хотя она в 8.2.13 уже была. Спасибо за идею!
Очень ценная статья!
Наконец-то начали использовать RMQ для обменов между конфигурациями на 1С.
Собственно, к этому уже давно шло. Возможно, когда-нибудь появится типовое тиражируемое решение.
И сам кей с использованием разношёрстных конфигураций очень полезный. Спасибо, что указали какие другие методы для обмена рассматривали (но даже там хотелось бы чуть-чуть подробнее, особенно почему решение от Акселота не катит).
Отдельно увидел ссылку на «Пулю» — было бы интересно увидеть как это решение организовано и работает. Возможно, какие-то сравнительные тесты и как использовали на практике.
(16) Мне ответил по почте руководитель отдела продаж, и сказал, что «Документацию предоставляем, кто приобрел dll, но саму документацию утерял.»
Вот я сижу и думаю, что за хиртый рекламный ход — размещать на страничке продукта кнопку «Скачать документацию PDF», а потом отказывать в этом?! )
(48) Согласен, для принятие решения, какой вариант использвать в проекте, надо больше информации и сравнительных тестов.
Такие тесты по идее могут себе позволить разработчики тиражных решений, но они точно будут предвзяты в свою пользу )
Мы руководствовались интуицией и здравым смыслом, бюджета и времени на принятие более взвешенных решений не было. И нам очень не хватало независимых мнений. Поэтому мы и написали эту статью, чтобы хоть как-то заполнить пробелы, и помочь членам нашего сообщества.
Баг, при котором затирается базовый тип у объектов при импорте xsd схемы вы как обошли?
(51) Ого, тоже через это прошли? )
Ну собственно как я и описал — избавились от ссылки на базовый тип Ref пакета ExchangeMessage. Просто перенесли его внутрь самого пакета ED и переписали на него ссылки всех ссылочных типов.
А до этого в явном виде указывали путь к ExchangeMessage внутри XSD-файла с помощью конструкции:
<xs:import schemaLocation=»\ServerEM.xsd» namespace=»http://www.1c.ru/SSL/Exchange/Message»/>
Только так он начинал видеть базовый тип Ref, а не AnyType.
Но это варварство каждый раз дергать файловую систему, поэтому решили радикально.
(52)
А до этого в явном виде указывали путь к ExchangeMessage внутри XSD-файла с помощью конструкции:
Только так он начинал видеть базовый тип Ref, а не AnyType.
А как без решения этого бага можно делать свой ED? Мы сейчас, например, берем, в УП добавляем в свой ED новый объект, теперь нужно обновить в БП его же, приходится делать через сравнение объединение конфигураций, потому что удалять-добавлять из буфера Пакет — а это значит менять идентификатор объекта метаданных, чего делать не хочется — GIT захламляется ненужными изменениями, да и сравнение-объединение не по наименованию при обновлении правильно использовать.
К слову, касательно «тоже» — Ваша статья сейчас выглядит так, как будто ее писал кто-то из моих коллег, причем большинство проблем решил и почему-то молчит. Я даже всех соавторов почекал.
Спасибо, что потрудились все выложить, тут материала намного больше, чем кажется и некоторые решения вызывают восхищение. И у нас как раз куплен rabbit MQ, но мы еще не остро столкнулись с медленной работой обмена, нет срочных требований этот обмен ускорить, поэтому не думали, как шину данных применять в этом кейсе.
(51) сталкивался, ещё не пробовал автоматизировать. Может быть поможет совет. В командном режиме выгрузить конфигурацию полностью или частично в файлы, посмотреть в каком виде оно там хранится, подменить файл пакета и загрузить обратно файлы в конфигурацию.
(54) Ага, почти так и делали. Только когда делаешь выгрузить конифгурацию в файлы, XDTO-пакет туда не попадает. Все гораздо проще делается:
Делаем «Экспорт XML-схемы». Делаем поиск и замену. Делаем «Импорт XML-схемы». Дальше появлется окно «Выбор обновляемых простанств имен», ставишь галочку — и все готово!
(55) При выгрузке/загрузке конфигурации XDTO-пакеты выгружаются/загружаются также как и все прочие объекты. Просто ему даётся расширение .bin. Но фактически это текстовый файл с xml-содержимым:
(56) Согласен, погорячился )
Только решил изучить, захожу а тут токая годнота.
Спасибо за статью!
Несколько не прозрачно, что именно выбрали для взаимодействия с RabbitMQ из 1С, YellowRabbitMQ?
Подскажите, рассматривали вариант взаимодействия через http api? Насколько он приемлем, есть ли ограничения? (скорость, количество запросов и т.д.)
Если правильно понимаю, такая возможность есть:
https://pulse.mozilla.org/api/
https://stackoverflow.com/questions/32486398/publishing-to-the-default-rabbitmq-exchange-using-the-http-api
(59) Отвечаю по пунктам:
1. Взяли YRMQ из коробки БИТ:Адаптер (сразу не разобрались, что концепция БИТ:Адаптер нам не подходит, иначе купили бы только YRMQ)
2. Мы тоже по-началу думали, что запросы HTTP можно реализовать средствами 1С и отказаться от внешней компоненты. Но, знающие люди подсказали, что это будет работать в разы медленее. Хотя и не привели никаких веских доказательств или замеров, кроме общедоступных: RPC работает на транспортном протоколе TCP, а HTTP изначально не транспортный протокол. Так что вопрос на самом деле остается открытым. Может кто сможет внятно объяснить или привести пруфлинки?
PS Если поискать в англоязычной среде, то можно найти те же самые выводы, но чуть более обоснованные:https://stackoverflow.com/questions/16838416/service-oriented-architecture-amqp-or-http
(60)
Тоже сразу подумал, про ограничения, http — это 250-500 запросов в секунду, никак не 150 000 )))
а Rabbit умеет MQTT -> AMPQ и это круто, конечно.
Надо подумать про YRMQ.
Просто в одном случае мы имеем доступное api от разработчика rabbit и возможности 1с для реализации, в другом прослойку native api с возможными ограничениями (там вроде же подписку надо покупать и компонента именная, утечет — будут проблемы).
Причем, как я вижу, для любых популярных языков работа с rabbitMQ — разжевана, 1с как всегда оставляет возможность разработать что-то самому и запаковать в компоненту.
Еще вопрос, почему отказались от 1с планов обмена как механизма регистрации изменений?) Объективно.
(61)
1. Насчет подписки — точно не обязательно. Она нужна скорее для поддержки и обновлений, чтобы получать возможные новые фичи. А насчет именной компоненты — спросим, на следующей неделе планировали в гости к парням заскочить.
2. Планы обмена не вписывались в концепцию быстрой передачи.Нам надо формировать XML-образ объекта в формате ED сразу, внутри транзакции при измененнии. Поэтому мы сделали РС «Очередь недоставленных сообщений» — по сути аналог плана обмена, С той лишь раницей, что у нас образ объекта формируется сразу на момент изменения, а таблицы изменений плана обмен хранят ссылки. И мы в любой момент готовы отказаться от этого промежуточного буфера, и отправлять сообщение сразу внутри транзакции, если будем иметь гарантию, что транзакция не прервется и каналы связи не заглючат. По поводу действий в конце транзакци транзакции — тут в форуме подсказали старый добрый ДобавитьОбработчик. А по поводу надежности канала — тут надо время пособирать статистику.
Хотя вот прям сейчас подумал, если использовать ДобавитьОбработчик, то последднюю милю по формированию сообщения в ED и его отправке можно пройти уже в фоновом задании, которое запускать прямо перед завершением транакции. В общем есть еще куда расти )))
(53)Мы сейчас, например, берем, в УП добавляем в свой ED новый объект, теперь нужно обновить в БП его же, приходится делать через сравнение объединение конфигураций, потому что удалять-добавлять из буфера Пакет — а это значит менять идентификатор объекта метаданных .
Тоже через это прошли. Поэтому вынесли наш пакет(ed) в хранилище значений отдельного справочника. Добавили к нему номер версии и автоматизировали создание и рассылку новой версии ed из базы кд3 по всем конфигурациям.
В шаге 2.1 вы пишете, что накладываете разделяемую блокировку на весь регистр объектов к отправке, что делает невозможным запись в этот регистр на время такой блокировки.
Т.е. во время отправки каждая транзакция записи объекта в БД, которая уже готова пополнить очередь отправки (заблокированный регистр), будет ждать окончания отправки, правильно понимаю?
(64) Всё верно, это защита от грязного чтения. Точно такой же эффект в механизме планов обмена.
Блокировка типа S накладывается на время выполнения запроса, это никому не мешающая пара миллисекунд, зато запрос читает только записи завершенных транзакций.
Если вдаваться в детали — блокировка S устанавливается не на всю таблицу, а на весь результат запроса — а это уже завершенные записи. Т.е. сам он никому не мешает, зато ему мешают незаконченные транзакции.
Но выше было описан способ как обойти эту проблему.
(65)
А, понятно, т.е. просто Запрос.Выполнить() в транзакции, что в худшем случае (8.2) блокирует считанный диапазон на запись только на время выполнения этого запроса, а в лучшем (8.3 или RCSI) вообще ничего не блокирует.
Я-то сначала думал, что речь о явной (устанавливаемой кодом) упр. блокировке, которая держится до конца транзакции (выгрузки), поэтому и «напрягся» 🙂
(67) ага, именно так:
НачатьТранзакцию();
Р = Запрос.Выполнить();
ЗафиксироватьТранзакцию();
(43)
Если учитывать что
То это логично, в БП виды номенклатуры соответствуют группам финансового учета (хотя он этого тоже не знает).
(61)
Да, Пуля подтвердила, компонента именная!
Годовая подписка на обновление компоненты — порядка 30тр. Брать или не брать — личное дело каждого. Мы например использовали старую версию, в которой еще не было метода сжатия сообщений, сейчас бы это пригодилось. И еще узнали про пару полезных фичей и исправленных багов. В общем для следующего проекта будем брать компоненту сразу у Пули. Сейчас активно изучаем Кафку (и вспоминаем Грегора Замзу )))
Спасибо за такой содержательный материал. Порадовала связка ED+Rabbit. Когда-то, когда появился самый первый курс по КД3, я спрашивал преподавателя, не является ли КД3 предтечей появления шины данных 1С. Он поговорил с разработчиками КД3 и ответил, что таких планов нет.
Спасибо за ваш труд, уверен, он будет очень полезен всем 1Сникам.
Не нашел ответа лишь на один вопрос, как дела у этой связки с производительностью. Понятно, что сам кролик быстр, но всё в комплексе? Если, к примеру, связи не будет сутки и накопится большая очередь? Когда-то мы сравнивали производительность обменов КД2 и КД3 и последняя была не на высоте, на наших объемах скорость выгрузки падала в разы, до загрузки даже и не доходило. Правда это было три года назад.
Плюс, событийная модель. Если «классический» обмен мы можем провести ночью, тем самым утилизируя сервера, когда нет пользователей, то в событийной модели мы как будто получим в базе-приемнике прирост количества пользователей на количество пользователей источника.
Я понял, что вы ограничили количество фоновых и тем самым снизили нагрузку, но хотелось бы услышать для какой системы приемлемы такие параметры? Сколько пользователей, сколько документов создается в чассутки, сколько сейчас «весит» база и как быстро растёт?
Есть ли у вас опыт применения в высоконагруженных системах, где в источнике и приемнике работают несколько сотен пользователей одновременно?
Понятно, что самое длительное – это проведение документов и его можно отложить на ночь, но тогда несколько теряется смысл, вроде данные доставили, а в отчетах всё равно получим информацию «завтра».
Любопытство не праздное — сами сейчас на распутье, КД2 уже «не вывозит», думаем на что заменить. Пока рабочий вариант — пустить НСИ через веб-сервисы (возможно с кроликом), а документы через КД2, но уже без справочной информации (только ссылки).
Спасибо за ответ и за предложение, обязательно воспользуюсь, когда появятся конкретные вопросы 🙂
А Вы не смотрели в сторону 2ИС:интеграции? Получается, что в Вашей схеме одно из ключевых преимуществ — многопоточность. В 2ИС она реализована на КД2, что называется «из коробки».
У нас очень много обменов написаны именно на КД2 и переписывать их с нуля — дорого и долго. Поэтому пробуем старые правила «заводить» на 2ИС, параллельно выделяя критичные для бизнеса места, которые нужно перевести на онлайн (те же НСИ).
(73) Да, 2iS:Интеграция смотрели, довольно мощный продукт, помимо интеграции там много чего полезного для администрирования. А параллельной загрузкой они вообще убили — выжали максимум из старой технологии КД2! Но все равно к 2ИС есть вопросы:
— может ли она обеспечить доставку объектов в режиме он-лайн (хотя бы за 10 секунд?)
— если там остался принцип пакетной передачи, то может ли она выборочно снимать с регистрации объекты с успешной доставкой, и оставлять регистрацию для объектов с неуспешной доставкой?
— остался ли КД2шный принцип написания правил «точка-точка»? Т.е. для обмена между 4 базами нам надо создать 12 комплектов правил КД2?
Я на все вопросы не отвечу, с 2ИС мы пока только пилотные обмены запустили. Когда будет более серьёзный опыт напишу.
Сейчас только по второму вопросу. Когда 2ИС не может записать объект, она делает несколько попыток (это может помочь, если ошибки возникают в результате блокировок). Если все попытки неуспешны, то она запоминает этот объект и повторно регистрирует его к отправке со следующим обменом. То есть ответ «да», она снимает объекты с успешной доставкой а неуспешные выгружает повторно. Далее, если вновь будет серия неуспехов, можно уведомлять админов. Режим «шины данных» заявлен, также заявлена поддержка КД3, но мы ещё их на практике не использовали.
(75) Понял, интересно, я бы почтал отчет о проекте на 2ИС! )
(75)
— мы тоже до этого додумались. Только неуспешные мы не выгружаем повторно, а запоминаем и отправляем оповещение в HelpDesk — дальше служба поддержки сама разбирается в причинах недоставки и устраняет их, прежде чем переотправить.
(74) Отвечу на Ваши вопросы по 2iS
1. Нельзя сказать, что это будем прям вот чистый онлайн, но расписание работы автозаданий обмена можно настраивать с любым произвольным интервалом запуска.
2. Может. Уважаемый tambu уже написал, могу к сказанному добавить, что есть настраиваемый параметр, который управляет, какое количество таких «неудачных» объектов считать порогом «неудачного» обмена. Т.е. если этот парамерт 100, а в процессе обмена неудалось записать 50 объектов — обмен все равно считается успешным. в противном случае регистрируется тревожное состояние и делаются рассылки оповещений.
3. К сожалению, остался. 🙁
(45) После обновления дизайна ИТС ссылка стала нерабочей
Зачем делать дополнительный костыль, отвечающий за доставку? Все же есть в XML файле универсального формата:
(79)
Как раз наоборот в случае использования шины данных костылём является квитование (нумерация сообщений и подтверждение доставки)
(80)
у вас есть система 1, система 2 и шина. Каким образом система 1 узнает, что в систему 2 было доставлено сообщение чтобы исключить повторную отправку данных?
С вашей точки зрения утрировано шина данных — это секс без обязательств
(81)
Кстати отличная метафора: событийная модель — это секс без обязательств!)))
В нашей концепции обязательства переложены на получателя. Если ему что-то не понравилось в полученном сообщении, он просит отправителя повторить.
Гарантию доставки сообщения даёт шина.
(0) а код всего решения где-то опубликован ?