- PVSM.RU - https://www.pvsm.ru -
В прошлом году к нам обратился ИТ-директор одного из крупнейших аграрно-промышленных холдингов в России. Подход к бизнесу, который реализовал наш клиент, был впечатляющим. Он одним из первых реализовал идею предприятия полного цикла – от поля до полки в продуктовом магазине. Благодаря доступности и высокому качеству продукции этот холдинг стал признанным брендом, который знают и выбирают. В тот момент в холдинг входило более 650 торговых точек и более 20 000 сотрудников, распределенных по всей территории РФ.
Заказчику требовалось обеспечить максимально быструю доставку чеков до центра со всех торговых точек России, включая продуктовые ларьки в глухих селах с эпизодическим Интернетом и минимальной компьютеризацией.
С учетом указанной специфики решение задачи превратилось в увлекательное приключение с бубном, шаманами и кроличьими лапками в лице RabbitMQ. Как мы строили федеративный кластер очередей и с чем столкнулись – под катом.
Холдинг с большим количеством распределенных торговых точек, работающий в условиях жесткой конкуренции, требовал от своих руководителей оперативного принятия управленческих решений. Для этого, руководителям требовалась информация по чекам в режиме «реального времени».
В действующей системе время доставки чека от кассы до центральной системы доходило до 3-х суток. При этом периодически фиксировалась не доведение информации о совершенной покупке (потеря чека).
Требовалось обеспечить получение информации о продажах «здесь и сейчас» для оптимизации доставки продукции в торговые точки и оперативного реагирования на изменение остатков товара и спроса. Эта информация должна одновременно попадать в центральную ИС холдинга на базе 1С и на компьютер товароведа в конкретном магазине/торговой точке.
Кроме того, требовалось обеспечить централизованную и оперативную переоценку товаров по сети, а также, подключить к BI-системе холдинга поток онлайн-данных со всех торговых точек.
В итоге, были сформированы критерии успешности проекта:
Для команды «Серебряной Пули» это была очень заманчивая штука, поскольку мы на тот момент уже разработали наш адаптер 1С для RabbitMQ и возможность запустить его в бой на больших расстояниях и нагрузках манила гиковские умы. Сама концепция “позиция чека в центре за 1 секунду” не так уж нова, мы еще в 2013 году презентовали идеи применения очередей [1] в 1С, и даже аппробировали ее на одной торговой сети, но на тот момент это были сильно экспериментальные костыли, включавшие помимо Rabbit+1С еще C#, WCF и даже немного С++.
Разумеется, мы это все подсмотрели в умных книжках, которые написались еще ранее. Поэтому, не возьмусь судить, когда именно идея очередей в интеграционных проектах начала захватывать мир.
Так или иначе, теоретическая часть и архитектурный концепт свою эффективность доказали, оставалось самая малость – все сделать, протестировать, пофиксить баги, задокументировать и задеплоить. :trollface:
Никто лучше владельца бизнеса не знает о его сильных и слабых сторонах, поэтому все интеграционные проекты начинаются с аудита процессов клиента, понимания отправной точки (AS IS). Обычно, обследование бизнеса включает в себя:
Чтобы исключить разночтения мы используем формализацию бизнес-процессов AS IS и TO BE в виде схем BPMN. Так и самим разбираться легче, и заказчику проще ничего не упустить, когда совместно с ним проходим по схеме процессов.
Из технических особенностей, в процессе аудита выяснили, что:
Схема интеграции AS-IS
Аудит также показал, что бизнес-процессы компании практически не нуждаются в корректировке, но требуется доработка инфраструктуры, обеспечивающая бесперебойное прохождение информации.
В общем и целом, перед нами стояла задача надежной доставки документов между тремя компонентами процесса: кассовым аппаратом, компьютером товароведа и центральным офисом. При этом, компьютер товароведа – это машина «под столом». Она может включаться/выключаться по желанию товароведа. Или вообще быть выключенной 23 часа из 24-х. Однако, при выходе из сумрака товаровед должен видеть актуальный набор цен, остатков, номенклатурных позиций и т.п.
Событийная интеграция на очередях уже давно стала общеупотребимым паттерном. Когда вам нужно передавать что-то куда-то, со многими звеньями, в ненадежной среде, и при этом потоки данных маршрутизировать – вам нужны события и очереди. Поэтому, мы выбрали RabbitMQ, поскольку он легко интегрируется в любую (нам так казалось) среду, включая платформу 1С, для которой у нас уже был собственноручно сделанный адаптер AMQP-протокола.
RMQ является своего рода менеджером потоков данных и позволяет обеспечить интеграцию в режиме «почти реального» времени, сохраняя при этом слабую связанность систем, выдерживая нагрузки, и прочее и прочее… Хороший сервер, одним словом, на Хабре про него написано немало.
Одной из приятных особенностей является кластеризация «из коробки» и возможность построения распределенных кластеров серверов, работающих совместно.
Мне всегда нравились картинки с архитектурой интеграции на очередях. Они всегда состоят из трех кубиков, в центре которых – брокер сообщений. Пусть такая картинка будет и в этой статье, дабы не нарушать канон.
При построении схемы встал вопрос – а где должен располагаться сервер очередей? В каких состояниях у нас может оказываться система? Выяснили, что существует 5 штатно-нештатных ситуаций при которых работа не должна останавливаться.
Чеки во всех этих ситуациях должны пробиваться, торговля не должна останавливаться. При восстановлении канала – чеки должны прибывать подписчику. Напомню, что торговая точка – это может быть и сельский ларек. Там не установлен отдельный сервер, на который можно было бы поставить RMQ. Получалось, что брокер сообщений должен стоять непосредственно на кассе. Сервера – это непозволительная роскошь, а Rabbit достаточно легковесный и вполне может работать на маленьком POS-терминале. Так почему бы и не да?
Разумеется, мы не стали делать POS единственной нодой кластера RMQ, но один из узлов федеративного кластера разместили прямо на торговом терминале, под управлением Windows Embedded. Сказать это было несколько легче чем сделать, но мы весело и азартно справились. О чем сейчас и расскажу.
Надо сказать, что Erlang и сам сервер RMQ на винду терминала встал практически без проблем. Проблемы возникли в клиенте, который должен взаимодействовать с сервером из кассового ПО.
Кассовое ПО Frontol имеет достаточно годную документацию, из которой мы выяснили, что имеется возможность кастомизировать поведение с помощью Javascript. «Йухху!» — сказали мы и принялись гуглить JS-клиент для RabbitMQ. Довольно быстро выяснилось, что нас ждет облом. На фронтоле не совсем Javascript. Ну т.е. формально да, синтаксис там такой же, но сама машина JavaScript там от Windows Script Host, того самого, который VBScript, cscript.exe и прочее. Если кратко, то он очень старый, микрософто-специфичный, и ни один вменяемый JS-клиент кролика на нем не заработает.
Однако, в экосистеме WSH можно использовать COM-объекты, и мы направились в сторону клиента RMQ для .NET [2].
Современные версии этого клиента уже не поддерживают .NET 3.5, который имелся в нашем распоряжении на POS-терминале, но к счастью, исходники клиента открыты, а кроме того, на гитхабе проекта сохранились теги, в которых .NET 3.5 все еще поддерживался. Слава Опенсорсу! Оставалось выкачать исходники старой версии .NET клиента, поставить там галочку Com-Visible и задеплоить на терминал.
Кассовое ПО имеет API, который можно использовать для взаимодействия.
function init() {
frontol.addEventListener("openDocument", "beforeOpenDocument", true);
frontol.addEventListener("closeDocument", "beforeCloseDocument", true);
frontol.addEventListener("closeDocument", "afterCloseDocument", false);
frontol.addEventListener("closeSession", "beforeCloseSession", true);
frontol.addEventListener("closeSession", "afterCloseSession", false);
addPolyfills(); // полифиллы рулят )
initRmqVariables();
createRMQConnection();
}
Возможности родного JS, который есть на борту Windows – крайне бедны. Например, там нет Array.indexOf или JSON.stringify. Но мир ведь не без добрых людей. Мы вспомнили популярный браузерный костыль по имени «полифиллы», и радостно встроили их в кассу. Если отбросить шутки в сторону, то все магические трюки с JS намеренно дотошно комментировались, чтобы поколения будущих админов могли четко и быстро понять – что происходит, откуда взялось и как работает.
Довольно быстро выяснилось, что JS-API не покрывает часть наших кейсов, однако, поскольку Frontol имеет в своем составе СУБД Firebird, а к ней существует ODBC-провайдер, то с помощью того же самого ADODB мы сможем из Javascript обращаться сразу в базу кассы и доставать там нужные нам данные.
function afterCloseSession() {
var connection = getDatabaseConnection();
var qSelect = new ActiveXObject("ADODB.Command");
qSelect.ActiveConnection = connection;
qSelect.CommandText =
"SELECT ChequeNumber " +
"FROM Document " +
"WHERE " +
" State = 1 " +
" AND(ChequeType IN(0, 1, 2)) "
Ну и наконец, непосредственная работа с сервером очередей из нашего JS выглядит следующим образом:
function createRMQConnection() {
factory = new ActiveXObject("RabbitMQ.Client.ConnectionFactory");
factory.UserName = rmqUser;
factory.Password = rmqPass;
factory.VirtualHost = "/";
factory.HostName = "localhost";
try {
rmqConnection = factory.CreateConnection(0);
} catch (e) {
throw new Error("Ошибка подключения к локальному серверу очередей. Обратитесь к администратору!n" + e.message);
}
rmqChannel = rmqConnection.CreateModel();
rmqMessageProperties = rmqChannel.CreateBasicProperties();
rmqMessageProperties.ContentType = "text/plain";
rmqMessageProperties.ContentEncoding = "string";
rmqMessageProperties.DeliveryMode = 2;
}
В архитектуру заложили следующие принципы:
В соответствии с архитектурным решением создана следующая схема потоков данных:
Полученная в результате схема обеспечивает заказанные характеристики по скорости и стабильно работает при выпадании любого из компонентов. После пропадания и восстановления связи накопленные данные уходят в центр в течении 5-10 секунд. На практике доказала свою эффективность технология слабо связанных систем. Все события происходят как будто в одном офисе, без учёта различного вида задержек, связанных с территориальной распределённостью и свойственной ей различной степенью доступности каналов связи.
Хочется отдельно порадоваться тому, в какое удивительное время мы живем. Еще недавно применение Open Source в продуктиве было этакого рода подвижничеством. «У вас открытое ПО работает? Ну и как вам по вкусу этот кактус?» Сегодня же, это абсолютная максима.
Я не могу себе представить компанию, в которой бы не было в продуктиве продуктов с открытым исходным кодом. Благодаря доступности информации, открытым исходникам, реализовывать бизнес-идеи стало намного проще и быстрее. Нужно поставить RMQ на древний нестандартный Javascript и Windows? Нет ничего проще. Нагугленное решение немного не подходит? – посмотри, как сделано и добавь недостающее. Time-to-Market при применении открытых продуктов сокращается в разы. А все знают, что быстрый выпуск решения означает конкурентное преимущество.
Github, Stackoverflow, открытые документации и стандарты позволяют за считанные недели запустить то, что раньше бы потребовало многолетней экспертизы в самых разных областях компьютерного знания.
Ну и конечно, отдельно радует, что сообщество 1С-ников с каждым годом все дальше выходит из своего закрытого мирка и вливается в глобальный IT. Например, «1C:Enterprise» на сегодня – это один из официальных языков, поддерживаемых Github, и «научили» его этому языку люди из сообщества 1С. Эта история, наверное, заслуживает отдельной статьи, возможно, я когда-нибудь ее напишу. А пока – всего вам доброго и удачи!
Спасибо за уделенное время!
Автор: EvilBeaver
Источник [3]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/programmirovanie/291358
Ссылки в тексте:
[1] презентовали идеи применения очередей: https://youtu.be/R1HQgOHEiME
[2] RMQ для .NET: https://github.com/rabbitmq/rabbitmq-dotnet-client
[3] Источник: https://habr.com/post/422151/?utm_campaign=422151
Нажмите здесь для печати.