
Ние сме отделът за развитие на технологии за търговската мрежа. Един ден ръководството постави задачата да ускори обемните изчисления, използвайки Apache Ignite в комбинация с MSSQL, и показа сайт с прекрасни илюстрации и примери с Java код. Сайтът веднага ми хареса , описание на който обещава чудеса: не е необходимо ръчно да разпускате Java или Scala кода на всеки възел в мрежата и да го разпускате отново всеки път, когато той се променя. В хода на работата се оказа, че Zero Deployment има специфики на употреба, особеностите на които искам да споделя. Под кат ще намерите размисли и подробности за реализацията.
1. Постановка на задачата
Същността на задачата е следната. Има справочник на търговските точки SalesPoint и справочник на продуктите Sku (Stock Keeping Unit). Търговската точка има атрибут „типМагазина“ със стойности „малък“ и „голям“. Към всяка търговска точка се свързва (зарежда от СУБД) асортимент (списък с продукти на търговската точка) и се подава информация за това, че от указаната дата посоченият продукт
се изключва от асортимента или се добавя в асортимента.
Необходимо е да се организира партициониран кеш на търговските точки и да се съхрани информация за свързаните продукти за един месец напред. Съвместимостта с боевата система изисква от клиентския възел Ignite да зарежда данните, да изчислява агрегат от вида (типМагазина, кодТовара, ден, брой_търговски_точки) и да ги изпраща обратно в СУБД.
2. Изучаване на литературата
Нямам все още опит, така че започвам от основите. Тоест, от преглед на публикации.
Статия от 2016 година съдържа линк към документацията на проекта Apache Ignite и същевременно упрек в неяснотата на тази документация. Прочетох я няколко пъти, но яснотата не идва. Обращам се към официалния урок , който
оптимистично обещава „Ще сте готови за работа за миг!“. Разглеждам настройките на променливите на средата, гледам две видеа Apache Ignite Essentials, но за моята конкретна задача те не се оказаха много полезни. Успешно стартирам Ignite от командния ред с стандартния файл „example-ignite.xml“, създавам първото приложение с помощта на Maven. Приложението работи и използва Zero Deployment, каква красота!
Чета нататък и там примера веднага използва affinityKey (създаден по-рано чрез SQL-запитване), и освен това се прилага загадъчният BinaryObject:
IgniteCache people
= ignite.cache("Person").withKeepBinary(); Прочетох : двоичен формат — нещо като рефлексия, достъп до полетата на обекта по име. Може да чете стойността на полето без пълна десериализация на обекта (икономия на памет). Но защо вместо Person се използва BinaryObject, след като има Zero Deployment? Защо IgniteCache<Key,Person> се превежда на IgniteCache<BinaryObject, BinaryObject>? Все още не е ясно.
Преобразувам Compute Application според моя случай. Първичният ключ на справочника за точки на продажба в MSSQL е определен като [id] [int] NOT NULL, създавам кеш по аналогия.
IgniteCache<Integer, SalesPoint> salesPointCache=ignite.cache("spCache")В xml-конфигурацията указвам, че кешът е партициониран.
<bean class="org.apache.ignite.configuration.CacheConfiguration">
<property name="name" value="spCache"/>
<property name="cacheMode" value="PARTITIONED"/>
</bean>Партиционирането по точки на продажба предполага, че необходимият агрегат ще бъде построен на всеки възел от клъстера за съществуващите записи в salesPointCache, след което клиентският възел ще извърши окончателното сумиране.
Чета туториал. , правя по аналогия. На всеки възел от клъстера стартирам IgniteRunnable(), горе-долу така:
@Override
public void run() {
SalesPoint sp=salesPointCache.get(spId);
sp.calculateSalesPointCount();
..
}Добавям логика за агрегация и износ, стартирам на тестов набор от данни. Локално на разработващия сървър всичко работи.
Стартирам два тестови сървъра CentOs, указвам IP адресите в default-config.xml, изпълнявам на всеки.
. /bin/ignite.sh config/default-config.xmlИ двата възела Ignite стартират и виждат един друг. Указвам нужните адреси в xml-конфигурацията на клиентското приложение, то стартира, добавя трети възел в топологията и веднага става отново два. В логовете е записано „ClassNotFoundException: model.SalesPoint“ в реда
SalesPoint sp=salesPointCache.get(spId);StackOverflow казва, че причината за грешката е — на сървърите CentOs няма потребителски клас SalesPoint. Приключихме. Какво става с „you don’t have to manually deploy your Java code on each node“ и по-нататък в текста? Или „your Java code“ — това не е за SalesPoint?
Вероятно съм пропуснал нещо — отново започвам да търся, чета и отново търся. След известно време ми се създава усещането, че съм прочел всичко по темата, няма нищо ново. Докато търсех, намерих няколко интересни забележки.
, Lead Architect at GridGain Systems, на StackOverflow, април 2016:
Model класовете не са внедрени в равни възли, но можете да използвате с флага withKeepBinary() за кеша и да заявите BinaryObjects. По този начин ще избегнете десериализация на страната на сървъра и няма да получите ClassNotFoundException.Още едно авторитетно мнение: , директор по управление на продуктите, GridGain Systems.
Статия на Хабре посочва три статии на Денис Магда: , , от 2016-2017 година. Във втората статия Денис предлага да стартирате узел на кластера чрез MaintenanceServiceNodeStartup.jar. Може също така да използвате стартиране с xml-конфигурация и команден ред, но тогава трябва ръчно да поставите потребителските класове на всеки разгръщан узел на кластера:
Това е всичко. Стартирайте (..) узел, използвайки файла MaintenanceServiceNodeStartup или предайте
maintenance-service-node-config.xml на скриптовете ignite.sh/bat на Apache Ignite.
Ако предпочитате последното, уверете се, че сте създали jar файл, който ще съдържа
всички класове от java/app/common и java/services/maintenance директории.
Jar файлът трябва да бъде добавен към classpath на всеки узел, където услугата
може да бъде разположена.Наистина, това е всичко. Ето защо, този загадъчен бинарен формат!
3. SingleJar
Денис заема първото място в личната ми класация, според мен най-полезният туториал от всичките налични. В неговия в GitHub е включен напълно готов пример за конфигуриране на узли на кластера, който компилира без никакви допълнителни трудности.
Правя по образ и подобие, получавам единен jar файл, който стартира „data node“ или „client node“ в зависимост от аргумента на командния ред. Сборката стартира и работи. Zero Deployment е победен.
Преминаването от мегабайти тестови данни до десетки гигабайти реални показателни данни показа, че бинарният формат има своята причина. Наложи се да оптимизирам разхода на памет на узлите, и тук BinaryObject се оказа много полезен.
4. Изводи
Първоначалната критика към неяснотата на документацията на проекта Apache Ignite се оказа валидна, от 2016 година не се е променило много. На начинаещите им е трудно да съберат работещ прототип на базата на сайта и/или репозитория.
В крайна сметка от извършената работа ми се стори, че Zero Deployment работи, но само на системно ниво. Приблизително така: BinaryObject се използва, за да научи отдалечените узли на кластера да работят с потребителските класове; Zero Deployment – вътрешен механизъм
на самия Apache Ignite и разпространява системните обекти из кластера.
Надявам се, моят опит да бъде полезен на новите потребители на Apache Ignite.
Източник: habr.com
