
Ние сме отдел за развитие на технологиите на търговската мрежа. Един ден ръководството постави задача да ускори обемните изчисления чрез използването на Apache Ignite в комбинация с MSSQL, като показа сайт с прекрасни илюстрации и примери на Java код. Сайтът веднага ми хареса , чийто описание обещава чудеса: не е необходимо ръчно да разгръщате Java или Scala кода си на всеки възел в мрежата и да го разгръщате отново всеки път, когато се променя. В хода на работата стана ясно, че Zero Deployment има специфики на използване, част от които искам да споделя. Под катa размисли и подробности за реализиране.
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<BinaryObject, BinaryObject> 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. Какво стана. Как така „не е нужно ръчно да разпределяте Java кода си на всеки възел“ и по-нататък по текста? Или „вашият Java код“ — това не е за SalesPoint?
Вероятно съм пропуснал нещо — отново започвам да търся, чета и отново търся. След известно време ми се струва, че съм прочел всичко по темата, няма нищо ново. Докато търсех, намерих няколко интересни забележки.
, водещ архитект в GridGain Systems, в StackOverflow, април 2016:
Моделните класове не се разпределят един на друг, но можете да използвате флага withKeepBinary() на кеша и да запитвате BinaryObjects. Така ще избегнете десереализацията на сървърната страна и няма да получите ClassNotFoundException.Още едно авторитетно мнение: , директор на управлението на продукта в GridGain Systems.
Статия на Хабра Три статии на Denis Magda: , , 2016-2017 години. Във втората статия Denis предлага да стартирате узел на кластера чрез 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
Denis заема първо място в личната ми класация, според мен е най-полезният туториал от всички налични. В неговия в GitHub се съдържа напълно готов пример за настройка на узли на кластера, който се компилира без никакви допълнителни усилия.
Правя по подобие и получавам единен jar файл, който стартира ‘data node’ или ‘client node’ в зависимост от аргумента на командния ред. Сборката стартира и работи. Zero Deployment е победен.
Преминаването от мегабайти тестови данни до десетки гигабайти реални показа, че бинарният формат съществува не напразно. Нужно беше да оптимизирам разхода на памет на нодовете, и тук BinaryObject се оказа много полезен.
4. Изводи
Първият срещан упрек в неясността на документацията на проекта Apache Ignite се оказа справедлив, от 2016 година се е променило малко. На новака не му е лесно да събере функциониращ прототип на базата на сайта и/или репозитория.
В резултат на извършената работа, впечатлението е, че Zero Deployment работи, но само на системно ниво. Приблизително така: BinaryObject се използва, за да се научат отдалечените узли на кластера да работят с потребителски класове; Zero Deployment — вътрешен механизъм
на самия Apache Ignite и разпространява системни обекти из кластера.
Надявам се, моят опит да бъде полезен на новите потребители на Apache Ignite.
Източник: habr.com
