Русский
Русский
English
Статистика
Реклама

Платформа

Из песочницы Javascript платформа Objectum

03.08.2020 22:10:54 | Автор: admin

Если вам нужен простой способ создавать веб-приложения, используя только javascript (full-stack), то предлагаю вам ознакомиться с платформой objectum. Новая версия платформы является результатом опыта работы над предыдущей версией, которая используется 10 лет. Обе версии используются в разработке различных информационных систем это региональные решения и системы для организаций. Платформа новой версии уже используется на продакшн серверах и будет развиваться длительное время. Далее подробности.


logo


Скрины из существующих разработок


Пример веб-приложения:




Пример 1




Пример сайта (без серверного рендера):




Пример 2




Пакеты платформы


Платформа состоит из следующих npm пакетов: objectum, objectum-client, objectum-proxy, objectum-react, objectum-cli


objectum


Собственно сама платформа, сервер приложений. Реализован ORM для работы с PostgreSQL. Работает достаточно быстро благодаря набору триггеров и функций (Objectum Database Engine), написанных на PL/pgSQL. Кэширование в Redis. Может работать в node cluster. Изменения данных журналируются и в случае чего виновника найти не проблема.


objectum-client


Изоморфный клиент для взаимодействия с objectum-proxy или objectum. Исходный код, работающий с хранилищем, без изменений можно запускать на клиенте или сервере. Клиент удобный, но если нужно, то взаимодействовать с сервером можно без клиента т.к. запросы, ответы в JSON.


objectum-proxy


Прокси расположен между objectum и objectum-client. Выполняет следующие задачи:


  • Выполнение серверных методов моделей
  • Выполнение серверных методов с правами администратора
  • Контроль доступа к базе данных. Отслеживаются все действия это действия CRUD и выборка данных через SQL.
  • Загрузка и получение файлов

objectum-react


Набор react компонентов UI. Используются bootstrap и fontawesome. Библиотеки redux, mobx не используются.
Оформление подключается в App.js. Под каждый проект использую разные bootstrap.css:


import "objectum-react/lib/css/bootstrap.css";import "objectum-react/lib/css/objectum.css";import "objectum-react/lib/fontawesome/css/all.css";

objectum-cli


Утилита командной строки. Выполняет сервисные действия с проектами, включая базы данных. Удобен для быстрого добавления моделей и записей.


Разработка


Чтобы не быть многословным, в этой статье напишу о самом простом подходе, где не нужно создавать свои компоненты React. В своих проектах я стараюсь по максимуму всю систему сделать таким способом. Для сложных интерфейсов нужно писать свои компоненты, где удобно подключать компоненты из objectum-react.
Теперь по порядку как создать проект objectum. Перед началом убедитесь, что у вас установлены NodeJS, PostgreSQL и Redis.
Готовый демо-проект catalog вы можете установить отсюда.




catalog




Установка платформы


Устанавливаем утилиту командной строки:


npm i -g objectum-cli

Устанавливаем платформу в папку /opt/objectum


mkdir /opt/objectumobjectum-cli --create-platform --path /opt/objectum

где параметры по умолчанию:


--redis-host 127.0.0.1 - хост и порт сервера Redis--redis-port 6379--objectum-port 8200 - порт, где будет работать objectum

Создание проекта


Создаем проект "catalog":


objectum-cli --create-project catalog --path /opt/objectum

Параметры по умолчанию:


--project-port 3100 - порт, где будет работать проект--db-host 127.0.0.1 - хост и порт сервера PostgreSQL--db-port 5432--db-dbPassword 1 - пароль пользователя catalog--db-dbaPassword 12345 - пароль администратора postgres--password admin - пароль администратора проекта

Папка проекта создается инструментом create-react-app. На клиенте и сервере модули подключаются как ES Modules.


Запуск


Запуск платформы:


cd /opt/objectum/server node index-8200.js

Запуск проекта:


cd /opt/objectum/projects/catalog node index-3100.jsnpm start

Должна открыться ссылка http://localhost:3000
В окне авторизации в полях логин, пароль вводим: admin




auth




Инструменты разработчика


Меню "Objectum" содержит пункты:


  • Модели создание моделей и свойств
  • Запросы создание SQL запросов для выборки данных
  • Меню конструктор меню для ролей пользователей
  • Роли здесь задается список ролей пользователей
  • Пользователи добавление пользователей



auth




Пакетное добавление данных в хранилище


Структура хранилища формируется с помощью UI, но для быстрого добавления большого количества данных лучше использовать objectum-cli.


Импорт JSON


cd /opt/objectum/projects/catalog  objectum-cli --import-json scripts/catalog-cli.json --file-directory scripts/files

Здесь скрипт catalog-cli.json
{    "createModel": [        {            "name": "Item",             "code": "item"        },        {            "name": "Item",             "code": "item",            "parent": "d"        },        {            "name": "Type",             "code": "type",            "parent": "d.item"        },        {            "name": "Item",             "code": "item",            "parent": "t"        },        {            "name": "Comment",             "code": "comment",            "parent": "t.item"        }    ],    "createProperty": [        {            "model": "d.item.type",             "name": "Name",             "code": "name",            "type": "string"        },        {            "model": "t.item.comment",             "name": "Item",             "code": "item",            "type": "item"        },        {            "model": "t.item.comment",             "name": "Date",            "code": "date",            "type": "date"        },        {            "model": "t.item.comment",            "name": "Text",            "code": "text",            "type": "string"        },        {            "model": "item",             "name": "Date",             "code": "date",            "type": "date"        },        {            "model": "item",             "name": "Name",             "code": "name",            "type": "string"        },        {            "model": "item",            "name": "Description",            "code": "description",            "type": "string",            "opts": {                "wysiwyg": true            }        },        {            "model": "item",             "name": "Cost",             "code": "cost",            "type": "number",            "opts": {                "min": 0            }        },        {            "model": "item",             "name": "Type",             "code": "type",            "type": "d.item.type"        },        {            "model": "item",             "name": "Photo",             "code": "photo",            "type": "file",            "opts": {                "image": {                    "width": 300,                    "height": 200,                    "aspect": 1.5                }            }        }    ],    "createQuery": [        {            "name": "Item",            "code": "item"        },        {            "name": "List",            "code": "list",            "parent": "item",            "query": [                "{\"data\": \"begin\"}",                "select",                "    {\"prop\": \"a.id\", \"as\": \"id\"},",                "    {\"prop\": \"a.name\", \"as\": \"name\"},",                "    {\"prop\": \"a.description\", \"as\": \"description\"},",                "    {\"prop\": \"a.cost\", \"as\": \"cost\"},",                "    {\"prop\": \"a.date\", \"as\": \"date\"},",                "    {\"prop\": \"a.photo\", \"as\": \"photo\"},",                "    {\"prop\": \"a.type\", \"as\": \"type\"}",                "{\"data\": \"end\"}",                "",                "{\"count\": \"begin\"}",                "select",                "    count (*) as num",                "{\"count\": \"end\"}",                "",                "from",                "    {\"model\": \"item\", \"alias\": \"a\"}",                "",                "{\"where\": \"empty\"}",                "",                "{\"order\": \"empty\"}",                "",                "limit {\"param\": \"limit\"}",                "offset {\"param\": \"offset\"}"            ]        },        {            "name": "Item",            "code": "item",            "parent": "t"        },        {            "name": "Comment",            "code": "comment",            "parent": "t.item",            "query": [                "{\"data\": \"begin\"}",                "select",                "    {\"prop\": \"a.id\", \"as\": \"id\"},",                "    {\"prop\": \"a.item\", \"as\": \"item\"},",                "    {\"prop\": \"a.date\", \"as\": \"date\"},",                "    {\"prop\": \"a.text\", \"as\": \"text\"}",                "{\"data\": \"end\"}",                "",                "{\"count\": \"begin\"}",                "select",                "    count (*) as num",                "{\"count\": \"end\"}",                "",                "from",                "    {\"model\": \"t.item.comment\", \"alias\": \"a\"}",                "",                "{\"where\": \"empty\"}",                "",                "{\"order\": \"empty\"}",                "",                "limit {\"param\": \"limit\"}",                "offset {\"param\": \"offset\"}"            ]        }    ],    "createRecord": [        {            "_model": "d.item.type",            "name": "Videocard",            "_ref": "videocardType"        },        {            "_model": "d.item.type",            "name": "Processor"        },        {            "_model": "d.item.type",            "name": "Motherboard"        },        {            "_model": "objectum.menu",            "name": "User",            "code": "user",            "_ref": "userMenu"        },        {            "_model": "objectum.menuItem",            "menu": {                "_ref": "userMenu"            },            "name": "Items",            "icon": "fas fa-list",            "order": 1,            "path": "/model_list/item"        },        {            "_model": "objectum.menuItem",            "menu": {                "_ref": "userMenu"            },            "name": "Dictionary",            "icon": "fas fa-book",            "order": 2,            "_ref": "dictionaryMenuItem"        },        {            "_model": "objectum.menuItem",            "menu": {                "_ref": "userMenu"            },            "name": "Item type",            "icon": "fas fa-book",            "parent": {                "_ref": "dictionaryMenuItem"            },            "order": 1,            "path": "/model_list/d_item_type"        },        {            "_model": "objectum.role",            "name": "User",            "code": "user",            "menu": {                "_ref": "userMenu"            },            "_ref": "userRole"        },        {            "_model": "objectum.user",            "name": "User",            "login": "user",            "password": "user",            "role": {                "_ref": "userRole"            }        },        {            "_model": "objectum.menu",            "name": "Guest",            "code": "guest",            "_ref": "guestMenu"        },        {            "_model": "objectum.menuItem",            "menu": {                "_ref": "guestMenu"            },            "name": "Items",            "icon": "fas fa-list",            "order": 1,            "path": "/model_list/item"        },        {            "_model": "objectum.role",            "name": "Guest",            "code": "guest",            "menu": {                "_ref": "guestMenu"            },            "_ref": "guestRole"        },        {            "_model": "objectum.user",            "name": "Guest",            "login": "guest",            "password": "guest",            "role": {                "_ref": "guestRole"            }        },        {            "_model": "item",            "name": "RTX 2080",            "description": [                "<ul>",                "<li>11GB GDDR6</span></li>",                "<li>CUDA Cores: 4352</span></li>",                "<li>Display Connectors: DisplayPort, HDMI, USB Type-C</span></li>",                "<li>Maximum Digital Resolution: 7680x4320</span></li>",                "</ul>"            ],            "date": "2020-06-03T19:27:38.292Z",            "type": {                "_ref": "videocardType"            },            "cost": "800",            "photo": "rtx2080.png"        }    ]}

Что всё это значит:


  • createModel создание моделей, где name наименование, code текстовый идентификатор, parent родитель. Иерархия используется для группировки моделей.
    • В примере создаются модели item, d.item.type, t.item.comment.
    • Модель "d.item.type" это справочник. В модели "item" ссылка на справочник из свойства "type". Все справочники рекомендуется добавлять в узел "d".
    • Модель "t.item.comment" это табличная часть. Комментарии имеют ссылку на "item". Все табличные части рекомендуется добавлять в узел "t".
  • createProperty создание свойств моделей, где name наименование, code текстовый идентификатор, model модель, type тип данных в т.ч. ссылка на любую модель, opts дополнительные параметры свойства, например, отображение текстового поля как wysiwyg редактор.
  • createQuery создание SQL запросов с JSON вставками блоков, параметров, моделей, свойств.
    • [] с помощью массива добавляется читаемый многострочный текст.
    • блоки {"...": "begin"}...{"...": "end"} помогают парсеру строить SQL запросы для различных целей: выборка (data), расчет кол-ва записей (count), фильтрация (where), сортировка (order), расчет кол-ва дочерних узлов (tree).
    • модель {"model": "item", "alias": "a"} конвертируется в название таблицы "код_id a".
    • свойство {"prop": "a.name"} конвертируется в название столбца "a.код_id".
    • параметр {"prop": "limit"} должен быть передан запросу при выполнении.
  • createRecord добавление записей моделей.
    • _model модель
    • name сохраняем любые свойства
    • [] с помощью массива добавляется читаемый многострочный текст.
    • _ref с помощью этой команды добавляем ссылки на другие записи т.к. заранее id записи неизвестно.
    • JSON конвертируется в текст.
    • "photo": "rtx2080.png" добавление файлов. В photo запишется "rtx2080.png" и загрузится файл из папки scripts/files.

Импорт CSV


cd /opt/objectum/projects/catalog  objectum-cli --import-csv scripts/stationery.csv --model item --file-directory/script/files --handler scripts/csv-handler.jsobjectum-cli --import-csv scripts/tv.csv --model item --file-directory/script/files --handler scripts/csv-handler.js

Возможности импорта CSV:


  • Импортирует строки из CSV как записи в указанную модель (item)
  • Импортирует файлы (изображения) из указанного каталога
  • С помощью обработчика загрузки меняются записи при добавлении (csv-handler.js):
    • Скрипт дополняет параметры в справочники в т.ч. в древовидный (категория)

Исходный код моделей


Исходный код ItemModel подключается на клиенте и сервере. Для добавления ReactJS или NodeJS кода нужно разделить код на ItemClientModel, ItemServerModel или на ItemModel, ItemClientModel extends ItemModel, ItemServerModel extends ItemModel.


Клиент


Подключение в App.js:


import ItemModel from "./models/ItemModel";store.register ("item", ItemModel);

Теперь создаваемые записи модели "item" будут экземплярами класса ItemModel:


let record = await store.createRecord ({    _model: "item",    name: "Foo"});

Что это дает:


  • Прямое обращение к свойствам record.name = "Bar";
  • Ссылка на хранилище record.store
  • Сохранение изменений await record.sync ()

ItemModel.js
import React from "react";import {Record, factory} from "objectum-client";import {Action} from "objectum-react";class ItemModel extends Record {    static _renderGrid ({grid, store}) {        return React.cloneElement (grid, {            label: "Items", // grid label            query: "item.list", // grid query            onRenderTable: ItemModel.onRenderTable, // grid table custom render            children: store.roleCode === "guest" ? null : <div className="d-flex">                {grid.props.children}                <Action label="Server action: getComments" onClickSelected={async ({progress, id}) => {                    let recs = await store.remote ({                        model: "item",                        method: "getComments",                        id,                        progress                    });                    return JSON.stringify (recs)                }} />            </div>        });    }    static onRenderTable ({grid, cols, colMap, recs, store}) {        return (            <div className="p-1">                {recs.map ((rec, i) => {                    let record = factory ({rsc: "record", data: Object.assign (rec, {_model: "item"}), store});                    return (                        <div key={i} className={`row border-bottom my-1 p-1 no-gutters ${grid.state.selected === i ? "bg-secondary text-white" : ""}`} onClick={() => grid.onRowClick (i)} >                            <div className="col-6">                                <div className="p-1">                                    <div>                                        <strong className="mr-1">Name:</strong>{rec.name}                                    </div>                                    <div>                                        <strong className="mr-1">Date:</strong>{rec.date && rec.date.toLocaleString ()}                                    </div>                                    <div>                                        <strong className="mr-1">Type:</strong>{rec.type && store.dict ["d.item.type"][rec.type].name}                                    </div>                                    <div>                                        <strong className="mr-1">Cost:</strong>{rec.cost}                                    </div>                                    <div>                                        <strong>Description:</strong>                                    </div>                                    <div dangerouslySetInnerHTML={{__html: `${record.description || ""}`}} />                                </div>                            </div>                            <div className="col-6 text-right">                                {record.photo && <div>                                     <img src={record.getRef ("photo")} className="img-fluid" width={400} height={300} alt={record.photo} />                                </div>}                            </div>                        </div>                    );                })}            </div>        );    }    // item form layout    static _layout () {        return {            "Information": [                "id",                [                    "name", "date"                ],                [                    "type", "cost"                ],                [                    "description"                ],                [                    "photo"                ],                [                    "t.item.comment"                ]            ]        };    }    static _renderForm ({form, store}) {        return React.cloneElement (form, {            defaults: {                date: new Date ()            }        });    }    // new item render    static _renderField ({field, store}) {        if (field.props.property === "date") {            return React.cloneElement (field, {showTime: true});        } else {            return field;        }    }    // item render    _renderField ({field, store}) {        return ItemModel._renderField ({field, store});    }};export default ItemModel;

В моделях зарезервированы названия методов для решения различных задач:


  • _renderGrid модель "item" имеет отображение по умолчанию в маршруте /model_list/item. Отображает компонент ModelList, который вызывает данный метод при рендере Grid.
  • _layout по маршруту /model_record/:id запись отображает компонент ModelRecord, который вызывает данный метод для получения разметки. Если метод не определен, то макет формы используется стандартный, где все поля по одной на строку, а табличные части в отдельных закладках формы.
  • _renderForm рендер формы
  • _renderField рендер поля. Статичный метод для новой записи и обычный метод для существующей записи.

Модифицированная форма:




auth




Сервер


Подключение в index.js:


import ItemModel from "./src/models/ItemServerModel.js";proxy.register ("item", ItemModel);

Методы и работа с хранилищем store такая же. Сессии между пользователями разделены.


ItemServerModel.js
import objectumClient from "objectum-client";const {Record} = objectumClient;function timeout (ms = 500) {    return new Promise (resolve => setTimeout (() => resolve (), ms));};class ItemModel extends Record {    async getComments ({progress}) {        for (let i = 0; i < 10; i ++) {            await timeout (1000);            progress ({label: "processing", value: i + 1, max: 10});        }        return await this.store.getRecs ({            model: "t.item.comment",            filters: [                ["item", "=", this.id]            ]        });    }};export default ItemModel;

С клиента серверные методы вызываются так:


getComments () {    return await store.remote ({        model: "item",        method: "getComments",        myArg: ""     });}

Доступ


Подключение в index.js:


import accessMethods from "./src/modules/access.js";proxy.registerAccessMethods (accessMethods);

access.js
let map = {    "guest": {        "data": {            "model": {                "item": true, "d.item.type": true, "t.item.comment": true            },            "query": {                "objectum.userMenuItems": true            }        },        "read": {            "objectum.role": true, "objectum.user": true, "objectum.menu": true, "objectum.menuItem": true        }    }};async function _init ({store}) {};function _accessData ({store, data}) {    if (store.roleCode == "guest") {        if (data.model) {            return map.guest.data.model [store.getModel (data.model).getPath ()];        }        if (data.query) {            return map.guest.data.query [store.getQuery (data.query).getPath ()];        }    } else {        return true;    }};function _accessFilter ({store, model, alias}) {};function _accessCreate ({store, model, data}) {    return store.roleCode != "guest";};function _accessRead ({store, model, record}) {    let modelPath = model.getPath ();    if (store.roleCode == "guest") {        if (modelPath == "objectum.user") {            return record.login == "guest";        }        return map.guest.read [modelPath];    }    return true;};function _accessUpdate ({store, model, record, data}) {    return store.roleCode != "guest";};function _accessDelete ({store, model, record}) {    return store.roleCode != "guest";};export default {    _init,    _accessData,    _accessFilter,    _accessCreate,    _accessRead,    _accessUpdate,    _accessDelete};

Любой запрос к хранилищу можно запретить или ограничить. Доступные методы:


  • _init инициализация модуля.
  • _accessCreate создание записей.
  • _accessRead чтение записей.
  • _accessUpdate изменений записей.
  • _accessDelete удаление записей.
  • _accessData выборка данных методом getData
  • _accessFilter для каждой модели в SQL запросе вызывается этот метод. Например ограничиваем конкретному пользователю выборку записей. Т.о. в любом новом запросе ограничения будут работать.

Действия можно запретить или ограничить, например разрешать изменять только набор свойств определенной роли.
Создание, изменение, удаление моделей, свойств, запросов и столбцов доступно только суперпользователю admin.


Действия администратора


Иногда нужно выполнить серверное действие с максимальными правами. Это может быть регистрация пользователя или какая-то обратная связь.
Подключение в index.js:


import adminMethods from "./src/modules/admin.js";proxy.registerAdminMethods (adminMethods);

admin.js
import fs from "fs";import util from "util";fs.readFileAsync = util.promisify (fs.readFile);function timeout (ms = 500) {    return new Promise (resolve => setTimeout (() => resolve (), ms));};async function readFile ({store, progress, filename}) {    for (let i = 0; i < 10; i ++) {        await timeout (1000);        progress ({label: "processing", value: i + 1, max: 10});    }    return await fs.readFileAsync (filename, "utf8");};async function increaseCost ({store, progress}) {    await store.startTransaction ("demo");    let records = await store.getRecords ({model: "item"});    for (let i = 0; i < records.length; i ++) {        let record = records [i];        record.cost = record.cost + 1;        await record.sync ();    }    await store.commitTransaction ();    return "ok";};export default {    readFile,    increaseCost};

Как видно из admin.js. Здесь читаем файлы и меняем данные из под любой учетной записи пользователя (guest).
С клиента вызов такой:


await store.remote ({    model: "admin",    method: "readFile",    filename: "package.json"});

Компоненты React


Библиотека содержит компоненты:


  • ObjectumApp веб-приложение
  • ObjectumRoute маршрут
  • Auth форма авторизации
  • Grid таблица
    • Параметр tree включает древовидную таблицу
  • Form форма
  • Tabs, Tab закладки
  • Fields поля для разных типов данных
    • StringField строка. Есть опции: textarea, wysiwyg
    • NumberField число
    • BooleanField чекер
    • DateField дата. Параметр showTime добавляет время.
    • FileField файл (изображение). Есть обрезание изображения перед загрузкой.
    • DictField выбор из справочника
    • SelectField выбор из списка
    • ChooseField ссылка на запись. Выбор элемента из другого компонента
    • JsonField составное поле. Содержит в себе любое количество полей различного типа. Значения сохраняются в виде строки JSON
    • Field используется внутри формы. Тип поля выбирается автоматически
    • JsonEditor многострочный редактор свойств JSON
  • Tooltip всплывающая подсказка
  • Fade анимация отображения
  • Action кнопка для выполнения функции

ObjectumApp


props:


  • locale локализация. Есть "ru".
  • onCustomRender свой рендер приложения
  • username, password автоматическая авторизация под выбранным пользователем (guest).

Grid


Для выборки данных компоненту нужно указать запрос (query) или модель (model). Предоставляет следующие функции:


  • Сортировка по выбранному столбцу
  • Фильтры по любым столбцам в соответствии с типом данных столбца
    • Сохранение настроенных фильтров в localStorage
  • Выбор отображаемых столбцов

Form


Форма группирует поля. Позволяет сохранить изменения, и загрузить файлы. Кнопка "Изменения" в форме показывает таблицу изменений по выбранному полю. Видно какой пользователь, когда и с какого IP-адреса внес изменения.


Action


Компонент предоставляет удобный запуск функций:


  • Параметр confirm подтверждение выполнения
  • Функция может быть синхронной или асинхронной
  • Во время выполнения:
    • Отображение прогресса выполнения, включая выполнение на сервере
    • Запрос подтверждения во время выполнения
    • В случае исключения показывает ошибку
  • Показывает результат если функция вернула строку

Отчеты


Для построения несложных отчетов используется createReport, который строит XLSX отчет. Пример:


import {createReport} from "objectum-react";let recs = await store.getRecs ({model: "item"});let rows = [    [        {text: "Список", style: "border_center", colSpan: 3}    ],    [        {text: "Наименование", style: "border"},        {text: "Дата", style: "border"},        {text: "Стоимость", style: "border"}    ],    ...recs.map (rec => {        return [            {text: rec.name, style: "border"},            {text: rec.date.toLocaleString (), style: "border"},            {text: rec.cost, style: "border"}                    ];    })];createReport ({    rows,    columns: [40, 10, 10],    font: {        name: "Arial",        size: 10    }});

Где:


  • rows это строки (row) отчета
  • colSpan, rowSpan работают как в HTML таблице
  • columns ширина колонок

Развертывание


Платформа поддерживает виртуализацию хранилищ. База любого проекта экспортируется в файл и импортируется в другую базу. В новой базе у ресурсов создаются ссылки на оригинальную базу, по которым виртуализированная база обновляется в дальнейшем. Модели, свойства, запросы, записи создаются, изменяются или удаляются. Примеры использования:


  • Я использую такую схему
    • БД catalog_dev разработка
    • БД catalog_test (импорт из catalog_dev) тестирование
    • БД catalog_"идентификатор клиента" (импорт из catalog_dev) продакшн
  • Общие и региональные справочники
    • БД region_dev разработка и общие справочники
    • БД region_"идентификатор региона" (импорт из region_dev) модификация общих справочников и добавление региональных параметров в справочники
    • БД region"идентификатор клиента региона" (импорт из region"идентификатор региона") продакшн
  • В одну БД можете импортировать несколько других БД, но в реальности мне это не понадобилось

Экспорт схемы catalog:


let $o = require ("../../server/objectum");$o.db.execute ({    "code": "catalog",    "fn": "export",    "exceptRecords": ["item"],    "file": "../schema/schema-catalog.json"});

Параметр exceptRecords отключает экспорт записей по выбранным моделям, включая дочерние модели.


Импорт схемы:


let $o = require ("../../../server/objectum");$o.db.execute ({    "code": "catalog_test",    "fn": "import",    "file": "../schema/schema-catalog.json"});

Производительность


В следующей таблице результаты тестирования наиболее трудоемкой функции создание записей. Тестировалось на MacBook Pro Mid 2014 (MGX82).


Журналируемые модели (model.unlogged: false):


Свойства 100 записей (сек.) 1000 записей (сек.) Записей в сек.
Кол-во: 1, Число: 1 0.5 4.9 204
Кол-во: 1, Строка: 1 0.5 4.6 215
Кол-во: 1, Дата: 1 0.5 4.4 227
Кол-во: 3, Число: 1, Строка: 1, Дата: 1 0.5 4.8 209
Кол-во: 10, Число: 10 0.6 5.8 172
Кол-во: 10, Строка: 10 0.6 7.1 140
Кол-во: 10, Дата: 10 0.6 10.1 98
Кол-во: 30, Число: 10, Строка: 10, Дата: 10 1.2 14.7 68
Кол-во: 100 Число: 100 2.3 27.3 37
Кол-во: 100 Строка: 100 2.4 24.1 42
Кол-во: 100 Дата: 100 2.3 24.6 40
Кол-во: 300 Число: 100, Строка: 100, Дата: 100 8.9 88.3 11

Нежурналируемые модели (model.unlogged: true):


Свойства 100 записей (сек.) 1000 записей (сек.) Записей в сек.
Кол-во: 1, Число: 1 0.5 4.3 233
Кол-во: 1, Строка: 1 0.4 4.1 244
Кол-во: 1, Дата: 1 0.4 3.7 268
Кол-во: 3, Число: 1, Строка: 1, Дата: 1 0.5 3.8 261
Кол-во: 10, Число: 10 0.5 4.1 243
Кол-во: 10, Строка: 10 0.4 4.0 251
Кол-во: 10, Дата: 10 0.4 4.2 239
Кол-во: 30, Число: 10, Строка: 10, Дата: 10 0.5 4.9 202
Кол-во: 100 Число: 100 0.6 12.4 81
Кол-во: 100 Строка: 100 0.7 6.1 162
Кол-во: 100 Дата: 100 0.9 7.2 140
Кол-во: 300 Число: 100, Строка: 100, Дата: 100 1.1 11.1 90


По столбцам:


  • в 1-м столбце указано количество свойств модели и типы данных
  • во 2-м и 3-м столбце указана продолжительность добавления записей
  • в 4-м столбце количество создаваемых записей в секунду.

Скрипт test.js


Заключение


Дополнительную информацию смотрите на домашних страницах пакетов на github. Каюсь, информация там скудная, буду стараться дополнять. Лицензия платформы MIT. В планах разработка дополнительных пакетов по аналитике и другим нужным направлениям.
Спасибо за внимание.

Подробнее..

Как создать микросервис на PaaS

08.12.2020 10:15:01 | Автор: admin
Если вам интересно, как можно автоматизировать повседневные задачи разработчиков и построить удобную систему оркестрирования зависимостей ваших сервисов, загляните под кат. Об этом в своем докладе на конференции Golang Live 2020 рассказал разработчик продуктовой команды Авито Auto B2B Иван Королев. Он затронул тему платформенных решений для создания микросервисов и на живом примере продемонстрировал, как происходит создание и развитие микросервиса в Авито.



Что такое Platform as a Service, и зачем она нужна?

Платформа снижает overhead на интеграцию с разными инфраструктурными частями, будь то базы данных или сервис по сбору логов и метрик. Если платформы в компании нет, то каждая продуктовая команда вынуждена заниматься этим вопросом самостоятельно. В лучшем случае решением могут стать библиотеки. В худшем свои костыли и велосипеды в каждом сервисе.

Платформа позволяет централизованно внедрять новые технологии в компании, опробовав их на не очень значимых для бизнеса сервисах и сформировав best practices. После этого она предлагает решать задачи единообразно.

Лучшие практики формируются не только по архитектурным решениям, но и по написанию кода и использованию отдельных библиотек.

Как в Авито появился PaaS


Рассмотрим инструменты инженеров Авито четыре года назад. Компания начинала с большого количества разных инструментов как для разработки, так и для эксплуатации. И инженеры работали со всем, что используется под капотом в любой облачной системе, будь то Kubernetes, сборка логов, ingress-контроллеры, шина данных для обмена асинхронными сообщениями.



В итоге самая большая сложность была в том, чтобы пригласить в продуктовые команды людей, которые знакомы хотя бы с частью этих инструментов. Иначе порог входа получался слишком высоким, и приходилось очень долго обучать новых сотрудников.

Три года назад мы использовали ванильный Kubernetes. И разработчики, получив определенные права на staging и на production, фактически выполняли роли системных администраторов. Они не только разрабатывали сервис, но и деплоили его, следили за ним, читали логи.

Конечно же, были шаблонные пайплайны для CI, которые упрощают выкатку. Не приходилось набирать команду в kubectl для выкатки руками. Но мы все равно использовали такие относительно низкоуровневые интерфейсы как kubectl. Позже появились helm-чарты, которые упрощают доставку сервиса, как набора Kubernetes-манифестов.

К чему мы пришли в итоге? Придумали штуку, которая называется PaaS и состоит из двух частей. Первая это консольная утилита, благодаря которой можно совершать все необходимые с сервисом, начиная от его создания, заканчивая доведением до продакшена, просмотром логов, разворачиванием в локальном окружении. Вторая часть PaaS dashboard.

Это графический интерфейс, который частично дублирует консольную утилиту, но предоставляет определенные удобства.

Все детали, вся подкапотная реализация скрыта от разработчиков за этими двумя интерфейсными штуками.

Какова же концепция PaaS? Максимально автоматизировать все, что можно автоматизировать, сокращая overhead на ручные действия продуктовых команд разработки. Бэклог PaaS основан на реальных потребностях инженеров, которые сформировались годами боли и крови. Помимо этого можно проводить опросы о том, что людям более приоритетно, а что менее. Таким образом к платформе можно относиться как к продукту, в котором решения принимаются на основе данных. Именно так формируется бэклог и roadmap развития.

Конечно же, у PaaS должен быть низкий порог входа. Благодаря этому разработчики концентрируются непосредственно на решении своих продуктовых задач, на продуктовой архитектуре, на архитектуре сервисов, а не на всем, что лежит под капотом.

В идеале нужно обеспечить нулевой overhead на интеграцию с инфраструктурой. Например, настройку подключений к базе данных (включая секреты), к кэшам, интеграцию в систему доставки логов. Хочется, чтобы разработчики не задумывались об этих вещах. Это не всегда получается, но к этому нужно стремиться, что реально при помощи PaaS.

Как это выглядит для пользователя?



У нас есть консольная утилита и PaaS-dashboard, в котором можно получить информацию о том, что делает конкретный сервис, какие технологии использует под капотом, на каком языке написан, кто ответственный, насколько сервис покрыт тестами, когда был последний деплой. То есть это дашборд состояния сервиса с нужными ссылками на Grafana, Jaeger, репозиторий.

Кроме того есть сводная информация для быстрого поиска проблем.

Можно понять, как сервис в целом себя чувствовал, почему он деградировал (была какая-то зависимость, или дело в железе, а может быть, в базе данных?).

За прошедшее время все больные места, которые находили в команде архитектуры, выглядели разнообразно. Особенно когда кто-то вместо решения продуктовых задач половину спринта тратил на то, чтобы развернуть сервис и PG Bouncer, настроить подключение к БД, связать все сервисы воедино. Таких проблем может быть очень-очень много.

В первую очередь мы идем от проблем к решениям. И я именно так буду рассматривать дальше весь жизненный цикл создания сервиса. Сначала мы будем обсуждать, что у нас болело, а потом к чему мы пришли, чтобы сделать жизнь разработчиков лучше.

Жизненный цикл сервиса довольно очевиден. Мы должны его создать. Затем его нужно протестировать, задеплоить в продакшн, и дальше успешно эксплуатировать.

Что требуется для создания сервиса


Для этого требуется создать репозиторий, зарегистрировать сервис в системе учета, описав, что это за сервис, какие у него функции, насколько он критичен, и так далее. И создать пачку ресурсов, разнообразные дашборды, завести пайплайны в CI, проект в Sentry. Разных систем может быть с десяток.

Кажется, это занимает лишь около часа. Но можно забыть создать какой-то ресурс, сделать это неправильно, узнать об этом через час, через два, через день, или только в продакшене. Чтобы избежать потенциальных проблем, хочется автоматизировать создание сервиса.

Для этого у нас есть утилита Avito Service Create, которая проводит разработчика по шагам, где он выбирает шаблон, а также указывает название, описание сервиса, тип:



В итоге мы получаем успешно созданный сервис, клонированный из определенного boiler plate репозитория, с заведенными проектами в TeamCity, Sentry и Grafana. Разработчик может этот сервис моментально задеплоить.

В результате, мы получаем:



Все это происходит под капотом, разработчику об этом не нужно думать.

Разработка сервиса с использованием PaaS


Главное, что болит при разработке без PaaS это отсутствие унификации. Сервисы у разных команд получаются разные, даже если они используют одинаковые подходы к проектированию. Это вызывает ряд проблем, когда хочешь прийти в другую команду и сделать им pull request. Для этого надо сначала разобраться, как устроен сервис другой команды, как он деплоится, как тестируется пройти весь спектр проблем новичка. Унификация позволила бы снять этот overhead на первичный вход.

Соответственно, метрики, логи, трейсы тоже могут писаться по-разному, и где искать их непонятно. А пока этого не узнаешь, сервис не задеплоишь. Интерфейсы взаимодействия сервиса могут быть не похожи с разными инфраструктурными частями. Например, у Kafka может быть несколько разных библиотек. Какая используется в сервисе? Кто знает.

В итоге получаем, что вход новых разработчиков сильно замедляется. Кроме того, сервис будет проблематично передать другой команде, если вдруг возникает такая потребность.

Что мы сделали, чтобы решить эту проблему? Договорились о единой структуре проектов для каждой технологии. Таким образом, переходя в другую команду, сотрудники примерно знают, как будет устроен проект. У сервисов есть базовые метрики и дашборды, логи в едином формате.

Кроме того, PaaS предоставляет единый RPC-протокол межсервисного взаимодействия. То есть разработчикам продуктовых команд не нужно изобретать свой собственный транспорт и думать, как интегрировать сервисы между собой.

Перейдем к конфигурации сервисов. Вначале у нас был Kubernetes и, соответственно, его чистые манифесты. Потом завезли helm-чарты, которые немножко упростили конфигурацию. Тем не менее, каждая продуктовая команда была вынуждена самостоятельно писать и поддерживать helm-чарты, и вообще иметь знания о том, как это должно быть устроено. Интересоваться best practices, натыкаться на одни и те же ошибки, даже несмотря на наличие документации.

В итоге мы получаем 40 килобайт манифестов в helm-директории каждого сервиса. При этом diff между этими манифестами в разных сервисах это, по сути, несколько строк. Люди копировали их из шаблона, заменяли нужные строки, и получался чистый копипаст между разными сервисами. И конечно же, они могли ошибиться в простыне yaml.

В итоге мы пришли к единому конфигурационному файлу, который называется app.toml и лежит в корне каждого проекта. Он представляет из себя именно те части сервиса, которые могут меняться: название, описание, движок под капотом, настройки для выкатки (например, CPU, память, количество реплик в разных окружениях):



Таким образом мы выносим в конфигурацию только то, что нужно изменять.
И у нас есть единый файл конфигурации с плоской структурой, в отличие от YAML.

Главная проблема в helm-чертах то, что они очень многословные. Приходится сидеть с линейкой и измерять, правильно ли сделан отступ у этой команды, иначе все сломается и не будет работать. TOML позволяет решить эту проблему.
Кроме того, сервисы конфигурируются через Environment-переменные, и их значение тоже хранятся в app.toml

Какие были проблемы с управлением секретами? Мы выбрали vault для хранения. Чтобы корректно его настроить, разработчику нужно понимать особенности его работы.

Нужно помнить о развесистой древовидной структуре ключей. UI далеко не самый удобный: в нем нет возможности просто прийти в корень и сходить к нужному ключу. Все ограничено правами доступа, и нужно точно знать путь с ключами сервиса, которые нужно поменять. Казалось бы ничего сложного, но это действие тоже требует когнитивной нагрузки.

Кроме того, нужно сделать интеграцию в helm-чартах, чтобы поднялись init-контейнеры, которые пойдут в vault и сформируют конфигурацию для podов.
И все это может упасть в самый неожиданный момент именно в продакшене.

Казалось бы, секреты та же самая часть конфигурации. Зачем сервису вообще знать, что за обычными конфигами надо идти в Env-переменные, а за секретными в vault? Это все можно объединить.

Мы изменяем секреты непосредственно в PaaS dashboard. Они раскатываются на namespace. Таким образом мы можем изолировать сервисы от друг друга. А сами сервисы получают секреты из переменных окружения, нам в этом помогает небольшой бинарник, который на старте контейнера сходит в vault и положит конфигурацию в Environment.

По межсервисному взаимодействию тоже есть большая боль.

Если его не унифицировать, то для каждого сервиса нужно писать клиент, возможно даже на двух-трех языках. Нужно не забыть обработать ошибки и подключить общие библиотеки, например, Circuit breaker. А еще необходимо прокинуть все хэдеры, которые нужны для межсервисного взаимодействия, например, для аутентификации.

И совсем космическая штука: выставить таймауты так, чтобы они укладывались в NFR сервиса. Простой пример: сервис, который на каждый hit ходит в базу данных, отвечает по секунде, и кто-то ходит в него с таймаутом в 200 мс. Такие штуки хочется отслеживать и настраивать адекватно.

К чему мы пришли в PaaS? У нас есть контракт в едином описании как для клиента, так и сервера. По этому описанию автоматически генерируется код. И уже в этом автосгенерированном коде (по сути, клиентской библиотеке или серверной) заложены все паттерны взаимодействия микросервисов. Там подключаются трейсинг, метрики и прочее.

Как это выглядит? У нас собственный формат описания. Он является подмножеством Protobuf или Thrift.



В итоге мы описываем сервис, RPC-ручки, DTO на входе и на выходе. Типы данных: скаляры, вложенные структуры, массивы, key-value.

Файл описывает как серверную часть, по которой генерирует серверный код, так и клиентскую. Клиенты, подключая тот или иной сервис, переносят, копируют себе используемые методы и поля в сообщениях, и непосредственно в их репозитории генерируется клиентский год.

Кроме того, есть возможность указать, что поле необязательное. Эти поля можно деприкейтить, переводить в статус необязательных. А после, когда все сервисы у себя использование поля выпилили, удалить это поле и в серверном описании.

Таким образом, из единого файла описания мы генерируем код для разных языков, и проблем с клиентскими библиотеками уже не возникает.

Кроме того, подключены метрики и Circuit breaker, единообразным образом настраиваются таймауты, передается контекст запроса, и вся микросервисная структура работает правильно.

Синхронное взаимодействие построено на внутреннем RPC протоколе, со стороны разработчика практически нет доступа к подробностям реализации. Ему неважно, каким образом на уровне транспорта у нас передаются данные: это JSON, или Protobuf, или Msgpack. Команда архитектуры таким образом развязывает себе руки на будущее, и может безболезненно внедрить новые протоколы, если это необходимо.

И в автогенерированных клиентах уже есть все, что нужно для работы. Подключение библиотек явное и единообразное. И переходя с задачами из сервиса в сервис, ты знаешь, как с этим работать.

Асинхронное взаимодействие у нас также построено поверх нашего протокола. Аналогично описывается формат взаимодействия: какие события этот сервис порождают, и какие события другого сервиса он потребляет.

Под капотом есть общий сервис data-bus, который инкапсулирует работу с Kafka. Все сервисы взаимодействуют уже непосредственно с ним.



Таким образом, собственный язык описания нам дает единый формат всей межсервисной коммуникации. При этом, синтаксис близок к Go, имеет простую структуру без импортов, и под капотом даже используется lexer, встроенный в Go.

Отсутствие vendor-lock позволяет использовать любой удобный протокол под капотом, и закрывает разработчиков от возможных проблем несовместимых изменений, как это бывает с Protobuf.

При этом, есть возможность накрутить разнообразную валидацию. Например, не дать задеплоить сервис в продакшен, если клиенты все еще используют какое-то поле или метод, который удалили.

Хранилища данных также подключаются через утилиту avito в 1 клик. Это дает разработчикам стандартные подходы к миграциям, прозрачную интеграцию сервиса с инфраструктурой и деплой хранилища в Kubernetes для удобства локальной разработки.

Выглядит это просто: мы выбираем хранилище, например Postgres, вводим одну команду, и зависимость добавляется в app.toml:



Подобным образом подключается Redis: мы выбираем тип хранилища: кэширующий в Kubernetes, c бекапами или без, шардированный вне Kubernetes. Зависимость от Redis также добавляется в app.toml, и дается рекомендация по подключению библиотеки к сервису.

Так описание хранилищ выглядит в app.toml: указывается тип хранилища, его размер, используемую версию. По этим данным генерятся манифесты для helm чарта:



И самое главное такое описание позволяет упростить локальную разработку.

К другим сервисам, от которых мы зависим, идем в стейджинг. Локальные хранилища деплоятся в minikube, включая локальную шину данных. А конфигурационный файл с Environment переменными генерируется на основе app.toml.

Так это выглядит для разработчика: происходит сборка и деплой в локальный кластер, поднимается база, мигратор, кэши и можно начать отладку. Локальное окружение получается максимально приближенным к продакшн.

Поговорим о тестировании


Классические боли тестирования в микросервисах: когда подходы, которые использовались в монолите по интеграционным тестам, в микросервисной архитектуре просто перестают работать. И завязывая десяток сервисов друг на друге в едином test suite, ты получаешь больше проблем, чем профита.

При этом, мы хотим покрывать наши тесты интеграционными кейсами для того, чтобы соблюсти пирамиду тестирования. Поэтому мы максимально стараемся использовать юнит-тесты, но при этом end-to-end тесты есть на критичных бизнес-путях. Для роутинга трафика между сервисами мы используем service mesh.

Какой существует подход? Например, у нас есть пять сервисов, которые взаимодействуют между собой. И мы хотим протестировать новую версию Service 3. Первое, что приходит в голову это развернуть в тестовом окружении весь комплект сервисов, которые взаимодействуют между собой. Но помимо того, что ресурсы не безграничны, это может привести к увеличению времени выполнения тестов и плохо повлиять на их стабильность.



Поэтому мы поднимаем Service 3 в тестовом окружении. Добавляем в запрос специальный заголовок, балансировщик трафика его принимает, разбирает и понимает, что Service 2 должен сходить с этим заголовком в новую версию Service 3, находящуюся в тестовом окружении. Таким образом мы сохраняем наш staging стабильным, но при этом позволяем end to end тестам работать с новыми версиями сервисов.

Фактически основная часть задач разработчика уже завершена. Но деплой у нас тоже лежит на командах разработки.

Deploy и эксплуатация


Каковы проблемы деплоя? Helm хороший инструмент, с его помощью можно создать высокоуровневое описание сервиса и всех его зависимостей. Тем не менее, с этим инструментом довольно трудно работать. У него много проблем и большое количество issues на github. Он не работает, когда необходимо поднять несколько кластеров для одного окружения, например, в staging или production. В этом случае все ломается, и helm не обеспечивает транзакционность деплоев. Ты не можешь гарантированно сказать, что у тебя все выкатилось в несколько окружений, и синхронно переключить трафик. В общем, начинается боль.

Поэтому команда архитектуры написала свой деплоер Jibe (он пока еще не в open source, но такие планы у ребят есть). Он решает задачу деплоя в несколько кластеров.

От helm по большей части была важна только генерация Kubernetes-манифестов, поэтому можно было, например, использовать helm для генерации, а непосредственно для деплоя Jibe. В дальнейшем можно будет генерировать манифесты самостоятельно.

Например, у нас есть два кластера, и сервис версии V5, которая задеплоена в оба кластера. Jibe, используя манифесты для новой версии, деплоит версию V6 в оба кластера:





Трафик в это время все еще идет на V5.

После того, как readiness check отработал, мы переключаем трафик со старых версий на новые. В такой схеме мы обеспечили транзакционность выкатки сервисов, но транзакционность переключений трафика может страдать. Это значит, что в неожиданный момент на этом этапе может отвалиться сеть, и в одном кластере, трафик переключится, а в другом нет. На этот случай есть автоматика, которая проверяет связанность кластеров с деплоером. И если что-то пойдет не так, версия откатится, обеспечивая таким образом минимальный рассинхрон между версиями в проде. Если же переключение трафика прошло хорошо, старая версия гасится.

Что мы получаем? Несколько стадий деплоя, каждая из которых может идти на полуручном приводе. Мы можем откатывать сервисы либо с помощью Canary, либо blue-green деплоем, и при этом получаем гарантию консистентности версий сервисов на всех кластерах.

Чем нам помогает PaaS с точки зрения эксплуатации? Типичная боль инфраструктурных команд: когда продуктовые команды заложили слишком большие запросы на capacity, на CPU и память. И в итоге пулл по запросам забит, но утилизация машин намного ниже, чем хотелось бы, и железо простаивает.

Кроме того, разработчикам необходимо самостоятельно планировать необходимое количество ресурсов для сервисов, пытаться определить будущую нагрузку. Эти значения могут со временем устаревать. Нужно не забывать держать их в актуальном состоянии. В итоге мы получаем просто плохой scheduling, соседство различных сервисов на одной и той же ноде, которые могут друг друга аффектить, и неэффективное использование ресурсов.

В Kubernetes есть механизм Vertical Pod autoscaling, который на основании статистики использования сервиса за предыдущее время может динамически подстраивать requests уже при следующем деплое.

Мы пришли к тому, что requests вычисляются на основании статистики, что позволяет разработчикам не задумываться об этом вопросе. В начале, когда создается сервис, разработчику дается довольно большой запас для обработки будущей нагрузки. А когда статистика накапливается, requests выравниваются. При этом лимиты задаются достаточно высокими, чтобы в случае резких всплесков нагрузки, их можно было пережить.

Service discovery часть, о которой разработчики тоже не хотят задумываться. Она должна быть скрыта за инфраструктурой, потому что иначе мы получаем зашивание URL непосредственно в конфигурации сервиса. Одни идут через ingress-контроллер, другие по fqdn-адресу Kubernetes. Случайно пошли из прода в стейджинг все сломалось. И появляется вопрос: как нам все это масштабировать, если у нас появляется новый кластер?

Что сделано у нас? В app.toml есть специальная секция с зависимостями сервиса:



Таким образом, у нас решается две проблемы. Проблема конфигурации. Из названия сервиса по определенному шаблону формируется ENV-переменная, в которую подставится URL, куда нужно стучаться. И вторая: таким образом мы можем сформировать граф зависимости каждого сервиса не на основании статистики, а просто по манифестам.

И разработчик тоже получает преимущество. Не нужно указывать никакие URL, система сама автоматически подставит нужный путь. А балансер, который стоит перед сервисом, передаст коннект к нужному сервису нужной версии. Например, в продакшен в случае canary, или в staging в случае такого кейса с тестированием.

Кроме того, автогенерируемые клиенты автоматически собирают все значения из ENV.
Кроме того, у нас есть опенсорсный инструмент Service Navigator (его можно будет посмотреть на нашем GitHub), который обеспечивает service mesh, и походы из одних сервисов в другие. Service Navigator собирает унифицированные метрики по всем взаимодействиям, и можно построить дашборды даже без участия и отправки метрик из сервисов. В навигаторе можно подключить разнообразные circuit breakers, переотправку запросов в случае ошибок. Все эти политики прозрачно настраиваются командой продуктовой разработки.

Под капотом используется Proxy Envoy, который балансит трафик, а Navigator занимается его динамической настройкой:



Таким образом у нас есть стандартные дашборды Observability, которые могут показать, что происходит с сервисом. По любому сервису можно получить единообразную информацию и даже отдебажить чужой сервис если метрики, которые для него написала команда разработки, недостаточно информативны.

Естественно, в Jagger есть связка с tracing. Envoy отправляет трейсы, и их все можно собрать в единую цепочку вызовов, чтобы посмотреть, где существует проблема.

Преимущества и недостатки PaaS


У любой системы есть недостатки. Главный недостаток PaaS в том, что со временем накапливается багаж сервисов. Они неплохо работают, поэтому никто не хочет их трогать, и бизнес-необходимости в этом нет. Кроме того, эти сервисы могут быть очень специфичными. Не все кейсы покрыты PaaS. Соответственно, миграция существующих сервисов может стать болевой точкой.

Важно соблюсти баланс между автоматизацией и гибкостью настройки.

Есть категория разработчиков, которым нравится возиться с низкоуровневыми деталями реализации, и они уже привыкли к имеющимся инструментам. Им может быть неприятно от того, что PaaS лишает их привычной части работы. Приходится тратить время на коммуникации. По нашему опыту, в итоге люди соглашаются с тем, что PaaS приносит больше радости, чем боли.

Однако PaaS в любом случае вносит ограничения в протокол взаимодействия, и их приходится либо принимать, либо обходить.

Какие у нас есть преимущества? Мы экономим время со стороны продуктовых команд, наш зоопарк технологий находится под контролем. Мы можем оповестить разработчиков о том, что вышла новая версия какой-нибудь библиотеки, или security patch. И радар технологий поддается осмыслению. Становится понятно, что используют команды у себя внутри в рамках большого Авито.

Кроме того, платформенная разработка развязывает себе руки, проводя любые операции по техническим усовершенствованиям внутри инфраструктуры без необходимости править код и helm-манифесты.

Выводы


PaaS обязателен для каждой компании, в которой количество разработчиков увеличивается от десятков до сотен.

PaaS можно рассматривать как продукт, позволяющий решить реальные проблемы людей и дать бизнесу возможность расти.

Я хочу закончить словами Расса Кокса о том, что разработка программного обеспечения появляется тогда, когда программирование добавляет время и других разработчиков. Это действительно так. И платформа это то, что должно появиться в каждой крупной компании. И чем раньше компания осознает необходимость этого, тем меньше техдолга накопится за время, пока платформы нет.

Даже в эпоху пандемии, мы совсем рядом.

Хотите получать полезные материалы о GO-разработке? Подписывайтесь на рассылку конференции GolangConf.
Подробнее..

Готовое решение для 3х кейсов по работе с карточками товаров на маркетплейсах

14.05.2021 14:06:19 | Автор: admin

Как повысить эффективность управления карточками товаров и грамотно работать с остатками на маркетплейсах? Этими вопросами задается каждый второй продавец, который хочет занять верхние строчки в поисковой выдаче и увеличить продажи. Разбираемся, какие особенности бывают при работе с карточками товаров, и как их решает RDV Маркет.

Кейс 1: несколько карточек соответствуют 1 товару

Такое происходит, когда один товар подходит под разные модели, либо же он размещен в нескольких категориях одновременно, чтобы получить больший охват клиентов. Тут возникает вопрос - как тогда транслировать цены и остатки на все карточки маркетплейсов, чтобы всё работало корректно?

Решение:

В личном кабинете маркетплейса, возьмем для примера Ozon, продавец заводит две позиции с разными артикулами чехол прозрачный для iPhone 7 и чехол прозрачный для iPhone 8. По факту это один товар, поскольку он подходит для обоих смартфонов.

Несмотря на то, что на маркетплейсе это две разные карточки, в 1С будут учитываться остатки по одному товару. При этом будет трансляция остатков и цен сразу на обе карточки.

Для этого в разделе "RDV:Товарный каталог", в "Управлении товарным предложением" нужно создать связку номенклатур. В этом документе отображается один товар в двух строках, артикул будет совпадать, но будут отличаться идентификаторы в личном кабинете и другие параметры, потому что на маркетплейсе одному товару соответствуют две карточки.

Если у продавца осталось, например, 50 чехлов, то при получении заказов остатки корректируются и транслируются на обе карточки маркетплейса.

Кейс 2: составные товарами и промонаборы

Это актуально тем, кто продает товары, требующие сборки, и/или комплектующие. Остатки по деталям могут использоваться в сборных товарах, часть из которых еще не собрана. Тут есть своя специфика: требуется считать количество возможных составных товаров с учетом остатков по комплектующим и транслировать остатки на маркетплейс.

Решение:

Например, поставщик торгует велосипедами на маркетплейсе Wildberries. В то же время он продает для них комплектующие: рамы, колеса, рули и сидушки. Когда у продавца есть достаточное количество комплектующих, он может собрать еще один велосипед и отправить его на маркетплейс.

Как это можно отобразить в системе 1С? В личном кабинете создаются две позиции: велосипед двухколесный и колесо, по которому передаются остатки.

Данные процессы осуществляются в документе "Управление товарным предложением". В нем указаны позиции велосипеда и шины с различными идентификаторами. На каждую позицию устанавливается цена и передается вместе с остатком.

Если продавец хочет сделать сборку, то в RDV Маркет можно создать варианты комплектации в разделе - "Варианты комплектации номенклатуры". Например, "Велосипед черный сборный", который состоит из трех частей: каркаса, сидушки и двух шин. Мы создаем вариант комплекта с указанием комплектующих - именно это увидит кладовщик в момент сборки. На основании этой информации 1С высчитывает, сколько велосипедов можно собрать.

Далее в отчете "Остатки и доступность товаров для маркетплейсов" продавец может посмотреть детальнее информацию по заказу. Рассмотрим тот же пример - "Велосипед черный сборный", по которому есть остаток на складе 1 шт. При этом 1С пишет, что для заказа доступно 15 шт. Почему так происходит? Все просто - продавец может собрать велосипеды из 3х позиций (каркас, сидушка, шина). И поскольку в наличии есть еще 14 сидушек для велосипеда, то эти данные 1С учитывает и транслирует на маркетплейс цифру 15. Если будет продана отдельно составляющая, например, шина, то остаток пересчитается.

Таким образом, работник склада в АРМ кладовщика увидит, если заказ дополнительно потребует сборки. Для этого нужно перейти в задание на сборку - собрать и отгрузить товар.

Кейс 3: Упаковки и штучные товары

Актуально, когда один товар продается как поштучно, так и упаковками (например, консервы для животных). В этом случае необходимо корректно транслировать остатки в разрезе штук и упаковок на маркетплейсах, а также отображать цены, если у продавца запланированы скидки.

Решение:

Допустим, поставщик продает на Яндекс.Маркете корм для кошек Whiskas в пакетиках. У него есть артикул и цена. Кроме того, у продавца в наличии такой же товар, который поставляется упаковками, состоящими из 24 шт. У упаковки другая цена и артикул. На странице товара на маркетплейсе можно увидеть, что эти товары относятся к одной карточке. Несмотря на это, продавец может транслировать остатки и цены как за одну штуку, так и за упаковку.

Как это реализовано в RDV Маркет? В "Управлении товарным предложением" создается товарное предложение, с помощью которого настраивается обмен по ценам и остаткам. С точки зрения учета у продавца будет один товар влажный корм Whiskas. Разница заключается в том, что он представлен в упаковке по 24 шт. и по 1 шт. В документе отображается один товар в двух строках, артикул совпадает, но отличаются упаковка и идентификаторы в личном кабинете.

Стоимость упаковки в 1С вычисляется автоматически, но при необходимости цену можно изменить. Это можно сделать в разделе "Установка цен товаров": нажать на кнопку "Создать", выбрать нужный маркетплейс и установить цену за одну штуку и упаковку. После проведения документа информация сразу уйдет на маркетплейс.

Таким образом, продавец отображает товар в карточке в двух вариантах, тем самым увеличивая объем продаж. При необходимости можно скрывать штучный товар и продавать его только упаковками.

Описанные кейсы и их решения актуальны для продавцов, работающих по модели FBS. Это связано с тем, что при торговле с собственного склада остатки меняются ежеминутно, поэтому сотрудникам необходимо постоянно обновлять сведения и следить за их актуальностью. В этом как раз помогает RDV Маркет, где учтены все особенности работы с карточками и остатками.

Подробнее..

Финуслуги как мы делаем платформу, которая изменит российский финансовый рынок

17.03.2021 10:08:48 | Автор: admin

В октябре прошлого года Московская биржа запустила платформу личных финансов finuslugi.ru. Об этом можно почитать, например, в официальном пресс-релизе на нашем сайте. Но кто читает скучные пресс-релизы, когда есть Хабр? Поэтому мы биржевая команда разработчиков решили рассказать здесь о проекте и о шишках, набитых на пути к его реализации.

Предвидим вопрос: кому вообще нужна отдельная платформа, чтобы управлять личными финансами? Есть банки (в том числе модные и технологичные), есть брокеры что еще надо? Объяснимся.

В 2018 году Банк России инициировал проект Маркетплейс. По задумке он должен объединить несколько онлайн-платформ, на которых будут заключаться сделки по разным финансовым продуктам. Финуслуги первая платформа, заработавшая в рамках проекта. Здесь можно выбрать и открыть вклад в одном из нескольких банков (еще купить ОСАГО, но об этом позже). А фишка в том, что сделать это можно полностью онлайн. Ходить в банк (и даже на его сайт) не нужно. Ни разу. Совсем.

Внимательный читатель справедливо возразит нам: многие банки давно умеют открывать вклады дистанционно. Зачем для этого городить огород и создавать отдельную платформу? В чем проблема-то? А вот в чем. Допустим, вы обслуживаетесь в зарплатном банке, и он действительно предлагает широкий спектр услуг и целую линейку вкладов. Но ни в одном из них вас не устраивает ставка, а бОльшую банк предложить не может. Ок, идем искать ставку повыше на один из агрегаторов, и И дальше начинается неудобство. Банк с высокой ставкой может не иметь офиса в регионе; завтра другой банк предложит ставки еще выше, и придется опять проходить эпопею с регистрацией и оформлением документов. И так далее, и тому подобное. А тут еще и пандемия

Вот тут-то в дело и вступает наша платформа.

Зарегистрировавшись на Финуслугах и пройдя идентификацию (курьер приедет туда, куда вам удобно), вы сможете открыть вклад в одном из банков-партнеров, не регистрируясь в нем (еще купить страховку, а в скором будущем взять кредит или купить ОФЗ-ны). А если где-то предложат более высокую ставку, то можно просто переложить деньги в другой банк-партнер. И самое главное Банк России обеспечивает законодательную базу и гарантию регистрации сделок (подробнее тут), АСВ страхует вклады, а значит, ничего с деньгами не может случиться.

В чём отличие от других платформ?

На рынке есть немало агрегаторов мы их уже вспоминали. Но Финуслуги от них отличаются, и довольно серьезно. Только на нашей платформе клиент проходит весь путь от выбора продукта до его оформления в одном личном кабинете, без визита в офис банка или перехода на его сайт. Система спроектирована так, чтобы клиент мог удобно и быстро получить нужную ему услугу.

Кроме того, информация о каждой платформенной сделке имеет статус золотой записи. Это значит, что она отражается в Регистраторе финансовых транзакций (РФТ), созданном Национальным расчетным депозитарием (НРД, входит в Группу Московская Биржа). В любой момент на Госуслугах можно получить выписку об операции, совершенной на Финуслугах. Такая выписка подтверждает юридическую силу сделки и при необходимости может быть предоставлена в качестве доказательства в суде.

Начало проекта

Мы уже писали, что проект зародился в 2018 году по инициативе Банка России. Почему проект в банковской сфере отдали на реализацию бирже, а не банку? Потому что биржа сторона нейтральная: мы не связаны цеховыми отношениями и не пытаемся подстроить платформу под интересы конкретных игроков рынка. Кроме Московской биржи в проекте приняли участие НРД, ряд банков и компаний-агрегаторов.

Мы сформировали основные направления разработки:

  • сама платформа;

  • интеграционный слой, содержащий механизмы взаимодействия с внешними организациями банками, курьерскими службами и т.д.;

  • и личный кабинет пространство конечного пользователя, где он может управлять своими финансами через интеграцию ЛК и платформы, выбирая вклад в одном из доступных агрегаторов.

Из-за больших масштабов проекта для его реализации требовалось немало ресурсов. Поэтому для разработки самой трудоемкой части платформы мы решили привлечь вендора. Впоследствии от этой идеи пришлось отказаться. Вся ключевая экспертиза в проекте сосредоточена именно платформе и ее интеграционном слое, развитие его только лишь силами вендора означало гораздо меньшую прозрачность разработки, высокие риски потери экспертизы и сложность поддержки.

Внутренняя экспертиза и немного Agile

В 2019 году пришлось изменить подход к развитию платформы. Активно менялись требования, закон еще не был принят, и поэтому пришлось повысить гибкость разработки, быстро адаптируясь к новым требованиям. В конце того года мы приняли несколько ключевых решений: отказались от внешних подрядчиков и перенесли к себе экспертизу по платформе, а также начали развивать свой агрегатор для подбора финансовых продуктов.

В 2020 году над проектом трудилось около 10 внешних и внутренних команд. Чтобы поддерживать прозрачность и отслеживание зависимостей, которых при разработке инкрементов было огромное количество, мы объединили все команды единым процессом, масштабировавшим классический Scrum. Так проект начал двигаться в сторону методологии Nexus, почерпнув оттуда такие полезные артефакты, как интеграционные команды, Nexus Sprint Planning, Nexus Daily Scrum и Nexus Sprint Retrospective.

Компонентный подход быстро показал свою несостоятельность. Мы поняли, что при взрывном росте продуктов тратим огромные ресурсы на синхронизацию взаимодействия между командами, не можем за короткий срок реализовать новую бизнес-историю и, самое главное, параллельно вести работу над новыми продуктами.

В итоге мы приняли самое простое решение: создать команды, которые смогли бы независимо делать свой продукт. Так появилась команды Вклады, Кредиты, Инвестиции, Страхование, выделились специальные сервисные команды для поддержки и развития общей функциональности системы Обработка платежей, Авторизация. Каждая команда может теперь сделать свой продукт от и до. Количество синхронизаций сократилось до минимума, на уровне общего API и общего дизайна. Это позволило в разы увеличить t2m для бизнесовых историй и циклы проверки гипотез.

Какая же архитектура позволила достичь такого решения?

Архитектура системы

В основе платформы лежит микросервисная архитектура. Причем ради информационной безопасности персональные данные и данные банковской тайны находятся в специальном защищенном сегменте. Бизнес-процессы в системе крутятся на Camunda. Продукты развёртываются в контейнерах с оркестрацией на основе Kubernetes. При этом CI/CD автоматизирован на всех этапах развертывания. Для бизнес-процессов реализован сквозной мониторинг на основе Dynatrace.

Сам технологический стек проекта обзорно представлен ниже:

Верхнеуровнево архитектура изображена на картинке, а сам сценарий использования выглядит так:

  1. банки передают в платформу свой каталог продуктов;

  2. клиент аутентифицируется на платформе (проходит идентификацию, если ещё не проходил) иоткрывает вклад (покупает продукт банка) из списка;

  3. через платежный хаб клиент перечисляет деньги;

  4. банк открывает вклад;

  5. а факт всех этих действий записывается в регистраторе финансовых транзакций.

При капитализации вклада и прочих финансовых транзакциях банк уведомляет платформу, которая, в свою очередь, также регистрирует эти транзакции в РФТ. При закрытии вклада деньги попадут в кошелек в платформе, и их можно будет вывести себе на карту или открыть другой вклад на более выгодных условиях.

Если у банка отзовут лицензию (а вдруг?), то Агентство по страхованию вкладов перечислит деньги на кошелек в платформе. Всё это произойдет автоматически, если вы дали на это согласие.

Сегодня, чтобы пользоваться Финуслугами, клиентам нужно однократно пройти личную идентификацию с нашим представителем. Почему бы не использовать для этого Единую биометрическую систему? Изначально мы так и планировали сделать. Но позднее биометрическую идентификацию исключили из 211-ФЗ и нам пришлось быстро перенастроить технологическую цепочку. Так появилось подтверждение личности с помощью курьера. Пока законодательством не предусмотрена возможность использования платформами биометрических данных пользователей. Но сейчас разрабатывается вторая версия законопроекта о финансовых платформах (Маркетплейс 2.0), где будет учтена биометрия. После изменения законодательства мы сможем отказаться от курьеров и перенести идентификацию полностью в онлайн.

Что дальше?

Банк России сопровождает в рамках платформы размещение вкладов, покупку облигаций, участие в ПИФах, страхование по ОСАГО и ипотечное кредитование. А другие участники рынка предлагают сберегательные сертификаты, В2В-продукты, а также иные страховые и кредитные продукты. В этом году мы планируем развивать и ОФЗ-ны, и кредитные услуги, а также создадим мобильное приложение для платформы.

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

Подробнее..

InterSystems IRIS универсальная AIML-платформа реального времени

24.08.2020 18:21:28 | Автор: admin
Автор: Сергей Лукьянчиков, инженер-консультант InterSystems

Вызовы AI/ML-вычислений реального времени


Начнем с примеров из опыта Data Science-практики компании InterSystems:

  • Нагруженный портал покупателя подключен к онлайновой рекомендательной системе. Предстоит реструктуризация промо-акций в масштабе розничной сети (допустим, вместо плоской линейки промо-акций теперь будет применяться матрица сегмент-тактика). Что происходит с рекомендательными механизмами? Что происходит с подачей и актуализацией данных в рекомендательный механизм (объем входных данных возрос в 25000 раз)? Что происходит с выработкой рекомендаций (необходимость тысячекратного снижения порога фильтрации рекомендательных правил в связи с тысячекратным возрастанием их количества и ассортимента)?
  • Есть система мониторинга вероятности развития дефектов в узлах оборудования. К системе мониторинга была подключена АСУТП, передающая тысячи параметров технологического процесса ежесекундно. Что происходит с системой мониторинга, ранее работавшей на ручных выборках (способна ли она обеспечивать ежесекундный мониторинг вероятности)? Что будет происходить, если во входных данных появляется новый блок в несколько сотен колонок с показаниями датчиков, недавно заведенных в АСУТП (потребуется ли и как надолго останавливать систему мониторинга для включения в анализ данных от новых датчиков)?
  • Создан комплекс AI/ML-механизмов (рекомендательные, мониторинговые, прогностические), использующих результаты работы друг друга. Сколько человеко-часов требуется ежемесячно для адаптации работы этого комплекса к изменениям во входных данных? Каково общее замедление при поддержке комплексом принятия управленческих решений (частота возникновения в нем новой поддерживающей информации относительно частоты возникновения новых входных данных)?

Резюмируя эти и множество других примеров, мы пришли к формулировкам тех вызовов, которые возникают при переходе к использованию механизмов машинного обучения и искусственного интеллекта в реальном времени:

  • Устраивает ли нас оперативность создания и адаптации (к меняющейся ситуации) AI/ML-разработок в нашей компании?
  • Насколько используемые нами AI/ML-решения поддерживают управление бизнесом в режиме реального времени?
  • Способны ли используемые нами AI/ML-решения самостоятельно (без разработчиков) адаптироваться к изменениям в данных и в практике управления бизнесом?

Наша статья это обстоятельный обзор возможностей платформы InterSystems IRIS в части универсальной поддержки развертывания AI/ML-механизмов, сборки (интеграции) AI/ML-решений и обучения (тестирования) AI/ML-решений на интенсивных потоках данных. Мы обратимся к исследованиям рынка, к практическим примерам AI/ML-решений и концептуальным аспектам того, что мы называем в этой статье AI/ML-платформой реального времени.

Что известно из опросов: приложения реального времени


Результаты опроса, проведенного среди около 800 ИТ-профессионалов в 2019 году компанией Lightbend, говорят сами за себя:


Рисунок 1 Лидирующие потребители данных реального времени

Процитируем важные для нас фрагменты отчета о результатах этого опроса в нашем переводе:

Тенденции популярности средств интеграции потоков данных и, одновременно, поддержки вычислений в контейнерах дают синергетический отклик на запрос рынком более оперативного, рационального, динамичного предложения эффективных решений. Потоки данных позволяют быстрее передать информацию, чем традиционные пакетные данные. К этому добавляется возможность оперативного применения вычислительных методов, таких как, например, основанные на AI/ML рекомендации, создавая конкурентные преимущества за счет роста удовлетворенности клиентской аудитории. Гонка за оперативностью также влияет на все роли в парадигме DevOps повышая эффективность разработки и развертывания приложений. Восемьсот четыре ИТ-специалиста предоставили информацию по использованию потоков данных в их организациях. Респонденты находились преимущественно в западных странах (41% в Европе и 37% в Северной Америке) и были практически равномерно распределены между малыми, средними и крупными компаниями.

Искусственный интеллект не хайп. Пятьдесят восемь процентов тех, кто уже применяет обработку потоков данных в продуктивных AI/ML-приложениях, подтверждают, что их применение в AI/ML получит наибольший прирост в следующем году (по сравнению с прочими приложениями).

  • По мнению большинства опрошенных, применение потоков данных в сценариях AI/ML получит наибольший прирост в следующем году.
  • Применение в AI/ML будет прирастать не только за счет относительно новых типов сценариев, но и за счет традиционных сценариев, в которых данные реального времени применяются все интенсивнее.
  • В дополнение к AI/ML, уровень энтузиазма среди пользователей пайплайнов IoT-данных впечатляет 48% из тех, кто уже интегрировал IoT-данные, утверждают, что реализация сценариев на этих данных получит существенный прирост в ближайшем будущем.

Из этого довольно интересного опроса видно, что восприятие сценариев машинного обучения и искусственного интеллекта как лидеров потребления потоков данных уже на подходе. Но не менее важным наблюдением становится и восприятие AI/ML реального времени через оптику DevOps: здесь уже можно начинать говорить о трансформации господствующей пока еще культуры одноразового AI/ML с полностью доступным набором данных.

Концепция AI/ML-платформы реального времени


Одной из типичных областей применения AI/ML реального времени является управление технологическими процессами на производстве. На ее примере и с учетом предыдущих размышлений, сформулируем концепцию AI/ML-платформы реального времени.
Использование искусственного интеллекта и машинного обучения в управлении технологическими процессами имеет ряд особенностей:

  • Данные о состоянии технологического процесса поступают интенсивно: с большой частотой и по широкому спектру параметров (вплоть до десятков тысяч значений параметров, передаваемых в секунду из АСУТП)
  • Данные о выявлении дефектов, не говоря уже о данных об их развитии, напротив, скудны и нерегулярны, характеризуются недостаточностью типизации дефектов и их локализации во времени (зачастую, представлены записями на бумажном носителе)
  • С практической точки зрения, для обучения и применения моделей доступно только окно актуальности исходных данных, отражающее динамику технологического процесса за разумный скользящий интервал, заканчивающийся последними считанными значениями параметров процесса

Эти особенности заставляют нас, помимо приема и базовой обработки в реальном времени интенсивного широкополосного входящего сигнала от технологического процесса, выполнять (параллельно) применение, обучение и контроль качества результатов работы AI/ML-моделей также в режиме реального времени. Тот кадр, который наши модели видят в скользящем окне актуальности, постоянно меняется а вместе с ним меняется и качество результатов работы AI/ML-моделей, обученных на одном из кадров в прошлом. При ухудшении качества результатов работы AI/ML-моделей (например: значение ошибки классификации тревога-норма вышло за определенные нами границы) должно автоматически быть запущено дообучение моделей на более актуальном кадре и выбор момента для запуска дообучения моделей должен учитывать как продолжительность самого обучения, так и динамику ухудшения качества работы текущей версии моделей (т.к. текущие версии моделей продолжают применяться, пока модели обучаются, и пока не будут сформированы их заново обученные версии).

InterSystems IRIS обладает ключевыми платформенными возможностями для обеспечения работы AI/ML-решений при управлении технологическими процессами в режиме реального времени. Эти возможности можно разделить на три основные группы:

  • Непрерывное развертывание (Continuous Deployment/Delivery, CD) новых или адаптированных существующих AI/ML-механизмов в продуктивное решение, функционирующее в режиме реального времени на платформе InterSystems IRIS
  • Непрерывная интеграция (Continuous Integration, CI) в единое продуктивное решение входящих потоков данных технологического процесса, очередей данных для применения/обучения/контроля качества работы AI/ML-механизмов и обменов данными/кодом/управляющими воздействиями со средами математического моделирования, оркестровку которых осуществляет в реальном времени платформа InterSystems IRIS
  • Непрерывное (само-)обучение (Continuous Training, CT) AI/ML-механизмов, выполняемое в средах математического моделирования с использованием данных, кода и управляющих воздействий (принимаемых решений), передаваемых платформой InterSystems IRIS

Классификация платформенных возможностей применительно к машинному обучению и искусственному интеллекту именно по таким группам неслучайна. Процитируем методологическую публикацию компании Google, в которой подводится концептуальная основа под эту классификацию, в нашем переводе:

Популярная в наши дни концепция DevOps охватывает разработку и эксплуатацию масштабных информационных систем. Преимуществами внедрения этой концепции становятся сокращение длительности циклов разработки, ускорение развертывания разработок, гибкость планирования релизов. Для получения этих преимуществ DevOps предполагает внедрение, как минимум, двух практик:

  • Continuous Integration (CI)
  • Continuous Delivery (CD)

Эти практики также применимы и к AI/ML-платформам в целях обеспечения надежной и производительной сборки продуктивных AI/ML-решений.

AI/ML-платформы отличаются от остальных информационных систем в следующих аспектах:

  • Компетенции команды: при создании AI/ML-решения, команда обычно включает дата-саентистов или экспертов-академиков в области исследования данных, которые проводят анализ данных, разработку и апробацию моделей. Эти участники команды могут и не быть профессиональными разработчиками продуктивного программного кода.
  • Разработка: AI/ML-механизмы экспериментальны по своей природе. Для того, чтобы решить задачу наиболее эффективным путем, требуется перебрать различные комбинации входных переменных, алгоритмов, способов моделирования и параметров модели. Сложность такого перебора заключается в трассировке что сработало/не сработало, обеспечении воспроизводимости эпизодов, генерализации разработок для повторяющихся внедрений.
  • Тестирование: тестирование AI/ML-механизмов требует большего спектра тестов, чем большинство других разработок. В дополнение к типовым модульным и интеграционным тестам тестируются валидность данных, качество результатов применения модели к обучающим и контрольным выборкам.
  • Развертывание: развертывание AI/ML-решений не сводится к предиктивным сервисам, применяющим единожды обученную модель. AI/ML-решения строятся вокруг многоэтапных пайплайнов, выполняющих автоматизированное обучение и применение моделей. Развертывание таких пайплайнов подразумевает автоматизацию нетривиальных действий, традиционно выполняемых дата-саентистами вручную для того, чтобы получить возможность обучить и протестировать модели.
  • Продуктив: AI/ML-механизмам может не хватать производительности не только из-за неэффективного программирования, но и вследствие постоянно изменяющегося характера входных данных. Иначе говоря, производительность AI/ML-механизмов может деградировать в связи с более широким спектром причин, нежели производительность обычных разработок. Что приводит к необходимости мониторинга (в режиме онлайн) производительности наших AI/ML-механизмов, а также рассылки оповещений или отбраковки результатов, если показатели производительности не соответствуют ожиданиям.

AI/ML-платформы схожи с другими информационными системами в том, что и тем, и другим необходима непрерывная интеграция кода с контролем версий, модульное тестирование, интеграционное тестирование, непрерывное развертывание разработок. Тем не менее, в случае с AI/ML, есть несколько важных отличий:

  • CI (Continuous Integration, непрерывная интеграция) больше не ограничивается тестированием и валидацией кода развертываемых компонент к ней также относится тестирование и валидация данных и AI/ML-моделей.
  • CD (Continuous Delivery/Deployment, непрерывное развертывание) не сводится к написанию и релизам пакетов или сервисов, а подразумевает платформу для композиции, обучения и применения AI/ML-решений.
  • CT (Continuous Training, непрерывное обучение) новый элемент [прим. автора статьи: новый элемент по отношению к традиционной концепции DevOps, в которой CT это, как правило, Continuous Testing], присущий AI/ML-платформам, отвечающий за автономное управление механизмами обучения и применения AI/ML-моделей.

Мы можем констатировать, что машинное обучение и искусственный интеллект, работающие на данных реального времени, требуют более широкого набора инструментов и компетенций (от разработки кода до оркестровки сред математического моделирования), более тесной интеграции между всеми функциональными и предметными областями, более эффективной организации человеческих и машинных ресурсов.

Сценарий реального времени: распознавание развития дефектов в питательных насосах


Продолжая использовать в качестве примера область управления технологическими процессами, рассмотрим конкретную задачу (уже упоминалась нами в самом начале): требуется обеспечить в реальном времени мониторинг развития дефектов в насосах на основе потока значений параметров технологического процесса и отчетов ремонтного персонала о выявленных дефектах.


Рисунок 2 Формулировка задачи по мониторингу развития дефектов

Особенностью большинства подобным образом поставленных задач на практике является то, что регулярность и оперативность поступления данных (АСУТП) должны рассматриваться на фоне эпизодичности и нерегулярности возникновения (и регистрации) дефектов различных типов. Другими словами: данные из АСУТП приходят раз в секунду правильные-точные, а о дефектах делаются записи химическим карандашом с указанием даты в общей тетради в цеху (например: 12.01 течь в крышку со стороны 3-го подшипника).

Таким образом, можно дополнить формулировку задачи следующим важным ограничением: метка дефекта конкретного типа у нас всего одна (т. е. пример дефекта конкретного типа представлен данными из АСУТП на конкретную дату и больше примеров дефекта именно этого типа у нас нет). Данное ограничение сразу выводит нас за рамки классического машинного обучения (supervised learning), для которого меток должно быть много.


Рисунок 3 Уточнение задачи по мониторингу развития дефектов

Можем ли мы каким-то образом размножить имеющуюся в нашем распоряжении единственную метку? Да, можем. Текущее состояние насоса характеризуется степенью подобия зарегистрированным дефектам. Даже без применения количественных методов, на уровне зрительного восприятия, наблюдая за динамикой значений данных, прибывающих из АСУТП, уже можно многое почерпнуть:


Рисунок 4 Динамика состояния насоса на фоне метки дефекта заданного типа

Но зрительное восприятие (по крайней мере, пока) не самый подходящий генератор меток в нашем быстроменяющемся сценарии. Мы будем оценивать подобие текущего состояния насоса зарегистрированным дефектам при помощи статистического теста.


Рисунок 5 Применение статистического теста к поступающим данным на фоне метки дефекта

Статистический тест определяет вероятность того, что записи со значениями параметров технологического процесса в полученном из АСУТП поток-пакете подобны записям метки дефекта определенного типа. Вычисленное в результате применения статистического теста значение вероятности (индекс статистического подобия) преобразуется к значению 0 или 1, становясь меткой для машинного обучения в каждой конкретной записи в исследуемом на подобие пакете. Т. е. после обработки вновь поступившего к нам пакета записей состояния насоса статистическим тестом у нас появляется возможность (а) добавить данный пакет в обучающую выборку для обучения AI/ML-модели и (б) осуществить контроль качества работы текущей версии модели при ее применении к данному пакету.


Рисунок 6 Применение модели машинного обучения к поступающим данным на фоне метки дефекта

В одном из наших предыдущих вебинаров мы показываем и объясняем, каким образом платформа InterSystems IRIS позволяет реализовать любой AI/ML-механизм в виде непрерывно исполняемых бизнес-процессов, осуществляющих контроль достоверности результатов моделирования и адаптирующих параметры моделей. При реализации прототипа нашего сценария с насосами мы используем весь представленный в ходе вебинара функционал InterSystems IRIS имплементируя в процессе-анализаторе в составе нашего решения не классический supervised learning, а скорее обучение с подкреплением (reinforcement learning), автоматически управляющее выборкой для обучения моделей. В выборку для обучения помещаются записи, на которых возникает консенсус детекции после применения и статистического теста, и текущей версии модели т. е. и статистический тест (после трансформации индекса подобия к 0 или 1), и модель выдали на таких записях результат 1. При новом обучении модели, при ее валидации (заново обученная модель применяется к собственной обучающей выборке, с предварительным применением к ней же статистического теста), записи, не удержавшие после обработки статистическим тестом результат 1 (из-за постоянного присутствия в обучающей выборке записей из изначальной метки дефекта), из обучающей выборки удаляются, и новая версия модели учится на метке дефекта плюс на удержавшихся записях из потока.


Рисунок 7 Роботизация AI/ML-вычислений в InterSystems IRIS

В случае, если возникает потребность в своего рода втором мнении по качеству детекции, получаемой при локальных вычислениях в InterSystems IRIS, создается процесс-советник для выполнения обучения-применения моделей на контрольном датасете с помощью облачных сервисов (например Microsoft Azure, Amazon Web Services, Google Cloud Platform и т. п.):


Рисунок 8 Второе мнение из Microsoft Azure под оркестровкой InterSystems IRIS

Прототип нашего сценария в InterSystems IRIS выполнен в виде агентной системы аналитических процессов, осуществляющих взаимодействия с объектом оборудования (насосом), средами математического моделирования (Python, R и Julia), и обеспечивающих самообучение всех задействованных AI/ML-механизмов на потоках данных реального времени.


Рисунок 9 Основной функционал AI/ML-решения реального времени в InterSystems IRIS

Практический результат работы нашего прототипа:

  • Распознанный моделью образец дефекта (12 января):


  • Распознанный моделью развивающийся дефект, не вошедший в образец (11 сентября, сам дефект был констатирован ремонтной бригадой только через двое суток 13 сентября):


Имитация на реальных данных, содержащих несколько эпизодов одного и того же дефекта, показала, что наше решение, реализованное на платформе InterSystems IRIS, позволяет выявить развитие дефектов данного типа за несколько суток до момента их обнаружения ремонтной бригадой.

InterSystems IRIS универсальная платформа AI/ML-вычислений реального времени


Платформа InterSystems IRIS упрощает разработку, развертывание и эксплуатацию решений на данных реального времени. InterSystems IRIS способна одновременно выполнять транзакционную и аналитическую обработку данных; поддерживать синхронизированные представления данных в соответствии с несколькими моделями (в т.ч. реляционной, иерархической, объектной и документной); выступать платформой интеграции широкого спектра источников данных и отдельных приложений; обеспечивать развитую аналитику в реальном времени на структурированных и неструктурированных данных. InterSystems IRIS также предоставляет механизмы для применения внешнего аналитического инструментария, позволяет гибко сочетать размещение в облаке и на локальных серверах.

Приложения, построенные на платформе InterSystems IRIS, внедрены в различных отраслях, помогая компаниям получать существенный экономический эффект в стратегической и операционной перспективах, повышая информированность принятия решений и устраняя зазоры между событием, анализом и действием.


Рисунок 10 Архитектура InterSystems IRIS в контексте AI/ML реального времени

Как и предыдущая диаграмма, нижеприведенная диаграмма сочетает новую систему координат (CD/CI/CT) со схемой потоков информации между рабочими элементами платформы. Визуализация начинается с макромеханизма CD и продолжается макромеханизмами CI и СТ.


Рисунок 11 Схема потоков информации между AI/ML-элементами платформы InterSystems IRIS

Суть механизма CD в InterSystems IRIS: пользователи платформы (разработчики AI/ML-решений) адаптируют уже имеющиеся и/или создают новые AI/ML-разработки с применением специализированного редактора программного кода AI/ML-механизмов: Jupyter (полное наименование: Jupyter Notebook; так же, для краткости, иногда называются и документы, созданные в данном редакторе). В Jupyter разработчик имеет возможность написать, отладить и убедиться в работоспособности (в т. ч., с использованием графики) конкретной AI/ML-разработки до ее размещения (развертывания) в InterSystems IRIS. Понятно, что создаваемая таким образом новая разработка будет получать только базовую отладку (т. к., в частности, Jupyter не работает с потоками данных реального времени) это в порядке вещей, ведь основным результатом разработки в Jupyter становится подтверждение принципиальной работоспособности отдельного AI/ML-механизма (на выборке данных показывает ожидаемый результат). Аналогичным образом, уже размещенный в платформу механизм (см. следующие макромеханизмы) перед отладкой в Jupyter может потребовать отката к доплатформенному виду (чтение данных из файлов, работа с данными через xDBC вместо таблиц, непосредственное взаимодействие с глобалами многомерными массивами данных InterSystems IRIS и т. п.).

Важный аспект имплементации CD именно в InterSystems IRIS: между платформой и Jupyter реализована двунаправленная интеграция, позволяющая переносить в платформу (и, в дальнейшем, обрабатывать в платформе) контент на языках Python, R и Julia (все три являются языками программирования в соответствующих ведущих open-source средах математического моделирования). Таким образом, разработчики AI/ML-контента имеют возможность осуществлять непрерывное развертывание этого контента в платформе, работая в привычном им редакторе Jupyter, с привычными библиотеками, доступными в Python, R, Julia, и выполняя базовую отладку (при необходимости) вне платформы.

Переходим к макромеханизму CI в InterSystems IRIS. На диаграмме изображен макропроцесс работы роботизатора реального времени (комплекс из структур данных, бизнес-процессов и оркестрируемых ими фрагментов кода на языках матсред и языке ObjectScript нативном языке разработки InterSystems IRIS). Задача этого макропроцесса: поддерживать необходимые для работы AI/ML-механизмов очереди данных (на основе потоков данных, передаваемых платформе в реальном времени), принимать решения о последовательности применения и ассортименту механизмов AI/ML (они же математические алгоритмы, модели и т. д. могут называться по-разному в зависимости от конкретики реализации и от терминологических предпочтений), поддерживать в актуальном состоянии структуры данных для анализа результатов работы AI/ML-механизмов (кубы, таблицы, многомерные массивы данных и т. д. для отчетов, дэшбордов и т. п.).

Важный аспект имплементации CI именно в InterSystems IRIS: между платформой и средами математического моделирования реализована двунаправленная интеграция, позволяющая исполнять размещенный в платформе контент на языках Python, R и Julia в их соответствующих средах с получением обратно результатов исполнения. Эта интеграция реализована как в режиме терминала (т. е. AI/ML-контент формулируется как код на ObjectScript, осуществляющий вызовы матсред), так и в режиме бизнес-процесса (т. е. AI/ML-контент формулируется как бизнес-процесс при помощи графического редактора, или иногда при помощи Jupyter, или при помощи IDE IRIS Studio, Eclipse, Visual Studio Code). Доступность бизнес-процессов для редактирования в Jupyter отражена при помощи связи между IRIS на уровне CI и Jupyter на уровне CD. Более детальный обзор интеграции со средами математического моделирования производится далее. На данном этапе, на наш взгляд, есть все основания для того, чтобы зафиксировать наличие в платформе всех необходимых инструментов для реализации непрерывной интеграции AI/ML-разработок (приходящих из непрерывного развертывания) в AI/ML-решения реального времени.

И главный макромеханизм: CT. Без него не получится AI/ML-платформы (хоть реальное время и будет имплементировано через CD/CI). Сутью CT является работа платформы с артефактами машинного обучения и искусственного интеллекта непосредственно в рабочих сессиях сред математического моделирования: моделями, таблицами распределений, векторами-матрицами, слоями нейросетей и т.п. Данная работа, в большинстве случаев, состоит в создании упомянутых артефактов в средах (в случае моделей, например, создание состоит из задания спецификации модели и последующего подбора значений ее параметров так называемого обучения модели), их применении (для моделей: расчет при их помощи модельных значений целевых переменных прогнозов, принадлежности к категории, вероятности наступления события и т.п.) и усовершенствовании уже созданных и примененных артефактов (например, переопределение набора входных переменных модели по результатам применения в целях повышения точности прогнозирования, как вариант). Ключевым моментом в понимании роли CT является его абстрагированность от реалий CD и CI: CT будет имплементировать все артефакты, ориентируясь на вычислительную и математическую специфику AI/ML-решения в рамках возможностей, предоставляемых конкретными средами. Ответственность за снабжение входными данными и доставку результатов будут нести CD и CI.

Важный аспект имплементации CT именно в InterSystems IRIS: пользуясь уже упомянутой выше интеграцией со средами математического моделирования, платформа имеет возможность извлекать из рабочих сессий, протекающих под ее управлением в матсредах, те самые артефакты и (самое важное) превращать их в объекты данных платформы. Например, таблица распределения, которая создалась только что в рабочей сессии Python может быть (без остановки сессии в Python) перенесена в платформу в виде, например, глобала (многомерного массива данных InterSystems IRIS), и использована для вычислений в другом AI/ML-механизме (реализованном уже на языке другой среды например, на R) или виртуальной таблицы. Другой пример: в параллель со штатным режимом работы модели (в рабочей сессии Python), на ее входных данных осуществляется авто-ML : автоматический подбор оптимальных входных переменных и значений параметров. И вместе со штатным обучением, продуктивная модель в режиме реального времени получает еще и предложение по оптимизации своей спецификации в которой меняется набор входных переменных, меняются значения параметров (уже не в результате обучения в Python, а в результате обучения альтернативной версии ее самой, например, в стеке H2O), позволяя общему AI/ML-решению автономно справляться с непредвиденными изменениями в характере входных данных и моделируемых явлений.

Познакомимся более подробно с платформенным AI/ML-функционалом InterSystems IRIS, на примере реально существующего прототипа.

На нижеприведенной диаграмме, в левой части слайда часть бизнес-процесса, имплементирующая отработку скриптов на Python и R. В центральной части визуальные логи исполнения некоторых из этих скриптов, соответственно, на Python и на R. Сразу за ними примеры контента на одном и другом языке, переданные на исполнение в соответствующие среды. В конце справа визуализации, основанные на результатах исполнения скриптов. Визуализации вверху сделаны на IRIS Analytics (данные забраны из Python в платформу данных InterSystems IRIS и выведены на дэшборд средствами платформы), внизу сделаны прямо в рабочей сессии R и выведены оттуда в графические файлы. Важный аспект: представленный фрагмент в прототипе отвечает за обучение модели (классификация состояний оборудования) на данных, поступающих в реальном времени от процесса-имитатора оборудования, по команде от процесса-монитора качества классификации, наблюдаемого в ходе применении модели. Об имплементации AI/ML-решения в виде набора взаимодействующих процессов (агентов) речь пойдет далее.


Рисунок 12 Взаимодействие с Python, R и Julia в InterSystems IRIS

Платформенные процессы (они же бизнес-процессы, аналитические процессы, пайплайны и т.п. в зависимости от контекста), прежде всего, редактируемы в графическом редакторе бизнес-процессов в самой платформе, причем таким образом, что создаются одновременно и его блок-схема, и соответствующий AI/ML-механизм (программный код). Говоря о том, что получается AI/ML-механизм, мы изначально подразумеваем гибридность (в рамках одного процесса): контент на языках сред математического моделирования соседствует с контентом на SQL (в т. ч., с расширениями от IntegratedML), на InterSystems ObjectScript, с другими поддерживаемыми языками. Более того, платформенный процесс дает очень широкие возможности для отрисовки в виде иерархически вложенных фрагментов (как видно в примере на приведенной ниже диаграмме), что позволяет эффективно организовывать даже весьма сложный контент, нигде не выпадая из графического формата (в неграфические методы/классы/процедуры и т. п.). Т. е. при необходимости (а она предвидится в большинстве проектов) абсолютно все AI/ML-решение может быть имплементировано в графическом самодукоментирующемся формате. Обращаем внимание на то, что в центральной части нижеприведенной диаграммы, на которой представлен более высокий уровень вложенности, видно, что помимо собственно работы по обучению модели (при помощи Python и R), добавляется анализ так называемой ROC-кривой обученной модели, позволяющий визуально (и вычислительно тоже) оценить качество обучения и этот анализ реализован на языке Julia (исполняется, соответственно, в матсреде Julia).


Рисунок 13 Визуальная среда композиции AI/ML-решений в InterSystems IRIS

Как уже упоминалось ранее, начальная разработка и (в ряде случаев) адаптация уже имплементированных в платформе AI/ML-механизмов будет/может производиться вне платформы в редакторе Jupyter. На диаграмме ниже мы видим пример адаптации существующего платформенного процесса (того же, что и на диаграмме выше) таким образом выглядит в Jupyter тот его фрагмент, который отвечает за обучение модели. Контент на языке Python доступен для редактирования, отладки, вывода графики прямо в Jupyter. Изменения (при необходимости) могут производиться с мгновенной синхронизацией в платформенный процесс, в т. ч. в его продуктивную версию. Аналогичным образом может передаваться в платформу и новый контент (автоматически формируется новый платформенный процесс).


Рисунок 14 Применение Jupyter Notebook для редактирования AI/ML-механизма в платформе InterSystems IRIS

Адаптация платформенного процесса может выполняться не только в графическом или ноутбучном формате но и в тотальном формате IDE (Integrated Development Environment). Такими IDE выступают IRIS Studio (нативная студия IRIS), Visual Studio Code (расширение InterSystems IRIS для VSCode) и Eclipse (плагин Atelier). В ряде случаев возможно одновременное использование командой разработчиков всех трех IDE. На диаграмме ниже показан пример редактирования все того же процесса в студии IRIS, в Visual Studio Code и в Eclipse. Для редактирования доступен абсолютно весь контент: и Python/R/Julia/SQL, и ObjectScript, и бизнес-процесс.


Рисунок 15 Разработка бизнес-процесса InterSystems IRIS в различных IDE

Отдельного упоминания заслуживают средства описания и исполнения бизнес-процессов InterSystems IRIS на языке Business Process Language (BPL). BPL дает возможность использовать в бизнес-процессах готовые интеграционные компоненты (activities) что, собственно говоря, и дает полные основания утверждать, что в InterSystems IRIS реализована непрерывная интеграция. Готовые компоненты бизнес-процесса (активности и связи между ними) являются мощнейшим акселератором сборки AI/ML-решения. И не только сборки: благодаря активностям и связям между ними над разрозненными AI/ML-разработками и механизмами возникает автономный управленческий слой, способный принимать решения сообразно ситуации, в реальном времени.


Рисунок 16 Готовые компоненты бизнес-процессов для непрерывной интеграции (CI) на платформе InterSystems IRIS

Концепция агентных систем (они же мультиагентные системы) имеет сильные позиции в роботизации, и платформа InterSystems IRIS органично ее поддерживает через конструкт продукция-процесс. Помимо неограниченных возможностей для начинки каждого процесса необходимым для общего решения функционалом, наделение системы платформенных процессов свойством агентности позволяет создавать эффективные решения для крайне нестабильных моделируемых явлений (поведение социальных/биосистем, частично наблюдаемых технологических процессов и т. п.).


Рисунок 16 Работа AI/ML-решения в виде агентной системы бизнес-процессов в InterSystems IRIS

Мы продолжаем наш обзор InterSystems IRIS рассказом о прикладном использовании платформы для решения целых классов задач реального времени (довольно подробное знакомство с некоторыми лучшими практиками платформенного AI/ML на InterSystems IRIS происходит в одном из наших предыдущих вебинаров).

По горячим следам предыдущей диаграммы, ниже приведена более подробная диаграмма агентной системы. На диаграмме изображен все тот же прототип, видны все четыре процесса-агента, схематически отрисованы взаимоотношения между ними: GENERATOR отрабатывает создание данных датчиками оборудования, BUFFER управляет очередями данных, ANALYZER выполняет собственно машинное обучение, MONITOR контролирует качество машинного обучения и подает сигнал о необходимости повторного обучения модели.


Рисунок 17 Композиция AI/ML-решения в виде агентной системы бизнес-процессов в InterSystems IRIS

На диаграмме ниже проиллюстрировано автономное функционирование уже другого роботизированного прототипа (распознавание эмоциональной окраски текстов) на протяжении некоторого времени. В верхней части эволюция показателя качества обучения модели (качество растет), в нижней части динамика показателя качества применения модели и факты повторного обучения (красные полоски). Как можно видеть, решение эффективно и автономно самообучилось, и работает на заданном уровне качества (значения показателя качества не падают ниже 80%).


Рисунок 18 Непрерывное (само-)обучение (CT) на платформе InterSystems IRIS

Об авто-ML мы тоже упоминали ранее, но на нижеприведенной диаграмме применение данного функционала показано в подробностях на примере еще одного прототипа. На графической схеме фрагмента бизнес-процесса показана активность, запускающая моделирование в стеке H2O, показаны результаты этого моделирования (явное доминирование полученной модели над рукотворными моделями, согласно сравнительной диаграмме ROC-кривых, а также автоматизированное выявление наиболее влиятельных переменных из доступных в исходном наборе данных). Важным моментом здесь является та экономия времени и экспертных ресурсов, которая достигается за счет авто-ML: то, что наш платформенный процесс делает за полминуты (нахождение и обучение оптимальной модели), у эксперта может занять от недели до месяца.


Рисунок 19 Интеграция авто-ML в AI/ML-решение на платформе InterSystems IRIS

Диаграмма ниже немного сбивает кульминацию, но это хороший вариант завершения рассказа о классах решаемых задач реального времени: мы напоминаем о том, что при всех возможностях платформы InterSystems IRIS, обучение моделей именно под ее управлением не является обязательным. Платформа может получить извне так называемую PMML-спецификацию модели, обученную в инструменте, не находящемся под управлением платформы и применять эту модель в реальном времени с момента импорта ее PMML-спецификации. При этом важно учесть, что далеко не все AI/ML-артефакты могут быть сведены к PMML-спецификации, даже если большинство наиболее распространенных артефактов это позволяют сделать. Таким образом платформа InterSystems IRIS имеет открытый контур и не означает платформенного рабства для пользователей.


Рисунок 20 Интеграция авто-ML в AI/ML-решение на платформе InterSystems IRIS

Перечислим дополнительные платформенные преимущества InterSystems IRIS (для наглядности, применительно к управлению технологическими процессами), имеющие большое значение при автоматизации искусственного интеллекта и машинного обучения реального времени:

  • Развитые средства интеграции с любыми источниками и потребителями данных (АСУТП/SCADA, оборудование, ТОиР, ERP и т. д.)
  • Встроенная мультимодельная СУБД для высокопроизводительной транзакционно-аналитической обработки (Hybrid Transaction/Analytical Processing, HTAP) любых объемов данных технологических процессов
  • Средства разработки для непрерывного развертывания AI/ML-механизмов решений реального времени на основе Python, R, Julia
  • Адаптивные бизнес-процессы для непрерывной интеграции и (само-)обучения механизмов AI/ML-решений реального времени
  • Встроенные средства Business Intelligence для визуализации данных технологических процессов и результатов работы AI/ML-решения
  • Управление API для доставки результатов работы AI/ML-решения в АСУТП/SCADA, информационно-аналитические системы, рассылки оповещений и т. д.

AI/ML-решения на платформе InterSystems IRIS легко вписываются в существующую ИТ-инфраструктуру. Платформа InterSystems IRIS обеспечивает высокую надежность AI/ML-решений за счет поддержки отказоустойчивых и катастрофоустойчивых конфигураций и гибкое развертывание в виртуальных средах, на физических серверах, в частных и публичных облаках, Docker-контейнерах.

Таким образом, InterSystems IRIS является универсальной платформой AI/ML-вычислений реального времени. Универсальность нашей платформы подтверждается на практике отсутствием де-факто ограничений по сложности имплементируемых вычислений, способностью InterSystems IRIS совмещать (в режиме реального времени) обработку сценариев из самых различных отраслей, исключительной адаптируемостью любых функций и механизмов платформы под конкретные потребности пользователей.


Рисунок 21 InterSystems IRIS универсальная платформа AI/ML-вычислений реального времени

Для более предметного взаимодействия с теми из наших читателей, кого заинтересовал представленный здесь материал, мы рекомендуем не ограничиваться его прочтением и продолжить диалог вживую. Мы с готовностью окажем поддержку с формулировкой сценариев AI/ML реального времени применительно к специфике вашей компании, выполним совместное прототипирование на платформе InterSystems IRIS, сформируем и реализуем на практике дорожную карту внедрения искусственного интеллекта и машинного обучения в ваши производственные и управленческие процессы. Контактный адрес электронной почты нашей экспертной группы AI/ML MLToolkit@intersystems.com.
Подробнее..

FlexCube внедрение революционной бэк-офисной платформы в Росбанке

22.06.2020 20:08:04 | Автор: admin
Друзья, привет!

Я Никита Климов, Platform Owner Oracle FlexCube (FCUBS) для процессинга операций корпоративных депозитов, межбанковских кредитов, валютных операций и деривативов в Росбанке. Сегодня я расскажу, как мы внедряли платформу FCUBS и в чем уникальность этого проекта для российского рынка. Все подробности под катом.

Начну с того, что мы стали первыми в России, кто рискнул адаптировать западную систему к реалиям российского учета в такой сложной продуктовой линейке, как финансовые рынки и рынки капитала. Задача усложнялась тем, что мы внедряли систему не с нуля, а на замену существующей системы, работающей в банке порядка 20 лет. Более того, система была обособленно расположена в периметре банка, а это значит, что нам предстояло разработать интеграцию со всеми внешними и внутренними системами.

Архитектура

Архитектура системы это классическая трехзвенка. В нашем случае backend это Oracle 12c (правда, он на текущий момент уже снят с поддержки, и мы переходим на 19сно это уже совсем другая история) и frontend IBM WebSphere. Искушенный читатель сразу задаст вопрос а почему не использовать нативный для Oracle Weblogic? И, безусловно, будет прав, потому что это первое, что рекомендовал нам сам Oracle. Но, так вышло, что для банка стандартом является именно сервер приложений IBM WebSphere, к тому же у нас ULA на этот продукт, и было принято решение адаптировать слой приложения под особенности WebSphere. Не сказать, что это было очень трудной задачей, однако ряд особенностей организации внутренних очередей все же имелся, и нашей команде пришлось провести немало часов на трехсторонних конф-коллах с поддержками Oracle и IBM.
image

В то время как мы пытались настроить тестовое окружение и показать проектной команде интерфейс, наши бизнес-аналитики проводили GAP анализ, описывали требования к функциональности и продумывали миграцию данных из старой системы. Не буду фокусироваться на миграции данных, т.к. по сути это процесс заполнения промежуточных, транспортных таблиц внутри FlexCube. Все это действо сводилось к итерационному наполнению и выверке данных до успешного выполнения миграции- ведь главное передать нужное значение в нужное поле таблицы.
Отличительная особенность нашего внедрения заключалась в том, что на замену системы с полным ручным приводом и постоянным пользовательским участием, мы создавали событийную систему на STP процессах, где предусматривалось минимальное вовлечение бизнес-пользователей. Предусмотрены лишь checkpoint для контроля процессинга. Для этого нам пришлось ломать старые бизнес-процессы и выстраивать новые.

Функциональность

Как я уже отметил ранее, система из коробки была совершенно не готова к российским реалиям, начиная с отсутствия плана счетов и заканчивая налоговым учетом. По сути это было просто ядро с набором событийных моделей, из которого надо строить космический корабль. Следовательно, вооружившись функциональными требованиями от бизнеса, мы приступили к разработке своего custom слоя на основе ядра системы. Мы разработали свой Accounting engine для генерации двадцатизначных счетов и приступили к реализации STP процессов. Исключить ручное вмешательство пользователей оказалось нетривиальной задачей, и не решалось лишь с помощью триггеров на уровне СУБД. Пришлось строить событийную логику на JOB и вводить расписание заданий. Этого тоже оказалось недостаточно, и мы вынуждены были использовать Quartz, на основе которого мы и автоматизировали наш workflow. В результате у нас в полностью автоматическом процессе происходит следующее:

  • Контракт попадает к нам из фронтовой системы Kondor+, и в зависимости от его суммы он либо автоматически авторизовывается, либо уходит на авторизацию к бизнесу;
  • После успешной авторизации система анализирует клиента является ли он клиентом головного офиса, а значит его счета лежат в GL1, либо это клиент регионов, а значит его счета лежат в GL2. Есть еще случай, когда это совершенно новый клиент, и тогда мы должны запросить его в нашей CRMсистеме и на основании полученной информации инициировать ему открытие необходимых счетов в соответствующей GL;
  • В результате процессинга система в режиме онлайн запрашивает остатки по счетам и при наличии таковых генерирует и передает в соответствующую GL необходимые проводки, формирует и отправляет SWIFT сообщения и платежки в ЕРЦ;
  • Внутри дня в системе происходят стандартные операции погашения, начисления процентов, досрочное закрытие и т.д;
  • Различную информацию о движениях по счету, контрагентах и контрактах мы автоматически передаем в ФНС, AML, Nostro. Также не забыли и об Интернет-Клиент Банке, через который клиенты видят, что происходит с их счетами после открытий и погашений депозитов;
  • Подготавливаем различную информацию для обязательной и управленческой отчетности и отдаем ее в DWH тут стоить отметить, что мы как делаем классические view для забора информации, так и генерируем транзакционные логи для IBM CDC, который в режиме онлайн забирает и агрегирует эту информацию.


Интеграция
image
Тут я для наглядности приложу нашу архитектуру и скажу лишь, что в связи с выбором frontend IBM WebSphere, было принято решение отказаться от стандартного для FCUBS Gateway, который разворачивается как дополнительное приложение и работает по старинке с листнерами и очередями, и перейти на работу c MDB Activation Specification. В результате чего мы разработали дополнительные интеграционные приложения, опубликовали их на нашем сервере и подключили к банковской интеграционной шине для взаимодействия с другими системами.
Кроме этого, у нас так же используется интеграция по средствам Systematica Modullar на основе TIBCO Rendezvous, общающийся с нашим фронтом и являющейся входной точкой для всех контрактов и ETL средство IBM DataStage. При этом функциональность на DataStage используется для интеграций, не связанных с DWH. Для одной из GL cпециально разработана логика батчевой загрузки\выгрузки данных, с проверкой статусов и breakpoints для ожидания вычислений.
image
ИТОГИ

  1. Заменили морально и технически устаревшую систему
  2. На основе ядра FlexCube создали свою платформу с неограниченными возможностями по параметризации и вариациям учета
  3. Минимизировали участие пользователей в процессе обработки дня
  4. Оптимизировали время выполнения EOD 15 минут вместо 3 часов ранее.
  5. Создали внутри банка центр компетенций и можем поддерживать и развивать платформу независимо от поставщика
  6. Практически неограниченно можем изменять usability пользовательского интерфейса и создавать любые проверочные экраны консолидированной информации для удобства контроля
  7. Внедрили систему мониторинга контрольных точек для беспрерывного процесса обработки
  8. Создали платформу, на которой готовы реализовать любой банковский продукт

image
Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru