Apache Ignite Zero Deployment: is it really Zero?

Apache Ignite Zero Deployment: is it really Zero?

We are the technology development department for the retail network. Once, management set a task to speed up large-scale computations by using Apache Ignite in conjunction with MSSQL, showing a site with wonderful illustrations and Java code examples. The site was immediately appealing. Zero Deployment, whose description promises wonders: you don’t have to manually deploy your Java or Scala code on each node in the grid and re-deploy it each time it changes. During the work, it turned out that Zero Deployment has specific usage characteristics, which I want to share. Below, I will provide thoughts and details of the implementation.

1. Problem Statement

The essence of the task is as follows. There is a directory of sales points SalesPoint and a directory of goods Sku (Stock Keeping Unit). Each sales point has an attribute 'typeStore' with values 'small' and 'large'. A range of products (the list of goods at the sales point) is loaded from the database, and information is provided regarding which goods will be excluded from or added to the assortment starting from a specified date.
Goods are excluded from the assortment or added to it.

It is required to organize a partitioned cache for sales points and store information about connected goods for a month in advance. Compatibility with the production system requires the Ignite client node to load data, calculate an aggregate of the form (typeStore, productCode, day, number_of_sales_points), and upload it back to the database.

2. Literature Review

I currently have no experience, so I am starting from scratch. That is, from an overview of publications.

The 2016 article Getting to Know Apache Ignite: First Steps contains a link to the Apache Ignite project documentation and a complaint about the obscurity of this documentation. I read it a couple of times, but clarity did not emerge. I turn to the official tutorial getting-started, which
which optimistically promises, 'You’ll be up and running in a jiffy!'. I am examining environment variable settings, watching two videos on Apache Ignite Essentials, but they turned out to be not very useful for my specific task. I successfully start Ignite from the command line with the standard file 'example-ignite.xml' and build my first application Compute Application using Maven. The application works and uses Zero Deployment; how beautiful!

I read further, and there is an example that immediately uses affinityKey (created earlier via SQL query), and a mysterious BinaryObject is also applied:

IgniteCache people 
        = ignite.cache("Person").withKeepBinary(); 

I read a little. a little: binary format — something like reflection, accessing object fields by name. It can read the value of a field without fully deserializing the object (saving memory). But why use BinaryObject instead of Person when there is Zero Deployment? Why is IgniteCache<Key,Person> translated to IgniteCache<BinaryObject, BinaryObject>? This is still unclear.

I am adapting the Compute Application for my case. The primary key of the sales point directory in MSSQL is defined as [id] [int] NOT NULL, I am creating a cache analogously.

IgniteCache<Integer, SalesPoint> salesPointCache=ignite.cache("spCache")

In the xml config, I specify that the cache is partitioned.

<bean class="org.apache.ignite.configuration.CacheConfiguration">
    <property name="name" value="spCache"/>
    <property name="cacheMode" value="PARTITIONED"/>
</bean>

Partitioning by sales points implies that the required aggregate will be built on each cluster node for the existing records in salesPointCache, after which the client node will perform the final summation.

I am reading the tutorial. First Ignite Compute Application, I am doing it by analogy. On each cluster node, I run IgniteRunnable(), something like this:

  @Override
  public void run() {
    SalesPoint sp=salesPointCache.get(spId);
    sp.calculateSalesPointCount();
    ..
  }

I am adding the aggregation and unloading logic, running it on the test data set. Locally on the development server, everything works.

I start two test servers CentOs, specifying the IP addresses in default-config.xml, running on each

.\/bin\/ignite.sh config\/default-config.xml

Both Ignite nodes start and see each other. I specify the necessary addresses in the xml config of the client application, it starts, adds a third node to the topology, and immediately the number of nodes goes back to two. The log states "ClassNotFoundException: model.SalesPoint" in line

SalesPoint sp=salesPointCache.get(spId);

StackOverflow says that the cause of the error is that the SalesPoint user class is not on the CentOs servers. We're stuck. What about "you don’t have to manually deploy your Java code on each node" and so on? Or is "your Java code" not about SalesPoint?

I probably missed something — I start looking again, reading, and searching again. After a while, I feel like I've read everything on the subject; there's nothing new left. While searching, I found several interesting observations.

Valentin Kulichenko, Lead Architect at GridGain Systems, response on StackOverflow, April 2016:

Model classes are not peer deployed, but you can use the withKeepBinary() flag
on the cache and query BinaryObjects. This way you will avoid deserialization
on the server side and will not get ClassNotFoundException.

Another authoritative opinion: Denis Magda, Director of Product Management, GridGain Systems.

Article on Habr about microservices refers to three articles by Denis Magda: Microservices Part I, Microservices Part II, Microservices Part III from 2016-2017. In the second article, Denis suggests starting a cluster node using MaintenanceServiceNodeStartup.jar. You can also use the launch with an XML configuration and command line, but in that case, you need to manually place the user classes on each deployed cluster node.

That's it. Start (..) node using the MaintenanceServiceNodeStartup file or pass maintenance-service-node-config.xml to Apache Ignite's ignite.sh/bat scripts. If you prefer the latter then make sure to build a jar file that will contain all the classes from java/app/common and java/services/maintenance directories. The jar has to be added to the classpath of every node where the service might be deployed.

Indeed, that’s it. Here it is, after all, the purpose of this mysterious binary format!

3. SingleJar

Denis takes first place in my personal ranking; in my opinion, it’s the most useful tutorial available. In his MicroServicesExample on GitHub, there is a fully working example of setting up cluster nodes, which compiles without any extra hurdles.

I am following the example and obtaining a single jar file that launches a ā€˜data node’ or ā€˜client node’ depending on the command line argument. The build is initiated and works. Zero Deployment has been conquered.

The transition from megabytes of test data to tens of gigabytes of production showed that the binary format exists for a reason. It was necessary to optimize memory usage on nodes, and at this point, BinaryObject proved to be very helpful.

4. Conclusions

The first encountered criticism regarding the clarity of the Apache Ignite project documentation turned out to be valid; not much has changed since 2016. It's not easy for a beginner to assemble a functioning prototype based on the website and/or repository.

As a result of the work done, it seems that Zero Deployment functions, but only at the system level. About this: BinaryObject is used to teach remote cluster nodes to work with user classes; Zero Deployment is an internal mechanism of Apache Ignite itself and distributes system objects across the cluster.
I hope that my experience will be useful to new users of Apache Ignite.

We are the technology development department.

Source: habr.com

Buy reliable website hosting with DDoS protection, VPS VDS servers šŸ”„ Buy reliable website hosting with DDoS protection, VPS VDS servers | ProHoster