
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. , 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 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 , 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 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. : 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. , 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.xmlBoth 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.
, Lead Architect at GridGain Systems, 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: , Director of Product Management, GridGain Systems.
Article on Habr refers to three articles by Denis Magda: , , 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 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
