We will start with Core classes and then will discuss about Lifecycle events, Client and Server mode, Thread pools configurations, Asynchronous support in Ignite and Resource injection.
Previous posts
Whenever you will be interacting with Apache Ignite in application, you will always encounter Ignite
interface and Ignition
class. Ignition
is the main entry point to create a Ignite
node. This class provides various methods to start a grid node in the network topology.
// Starting with default configuration
Ignite igniteWithDefaultConfig = Ignition.start();
// Ignite with Spring configuration xml file
Ignite igniteWithSpringCfgXMLFile = Ignition.start("/path_to_spring_configuration_xml.xml");
// ignite with java based configuration
IgniteConfiguration icfg = ...;
Ignite igniteWithJavaConfiguration = Ignition.start(icfg);
There are also other useful methods in Ignition
class which we will discuss in a bit. Ignite
interface provide control over node. It has various methods to interact as data-grid, service-grid, compute-grid, schedular and many more.
Apache Ignite provides four LifecyleEvents
i.e. BEFORE_NODE_START
, AFTER_NODE_START
, BEFORE_NODE_STOP
and AFTER_NODE_STOP
. It provide hook to tap these events. You need to implement LifecycleBean
and set the implementation in the ignite configuration.
class IgniteLifecycleEventListener implements LifecycleBean {
@Override
public void onLifecycleEvent(LifecycleEventType evt) throws IgniteException {
String message;
switch (evt) {
case BEFORE_NODE_START:
message = "before_node_start event is called!";
break;
case AFTER_NODE_START:
message = "after_node_start event is called!";
break;
case BEFORE_NODE_STOP:
message = "before_node_stop event is called!";
break;
case AFTER_NODE_STOP:
message = "after_node_stop event is called!";
break;
default:
message = "Unknown event";
break;
}
System.out.println(message);
}
}
Apache Ignite node can be run in client or server mode. Server nodes participates in Computing, Caching, data grid, service grid etc. and client nodes are way to interact with server nodes to have near time caching, transaction, computing, service grid functionality. You need to explicitly define the client and server mode.
IgnitionConfiguration.setClientMode(...);
Ignition.setClientMode(...);
System thread pool
It processes all cache related operations except SQL and some other queries and also handles computing cancellation tasks.
IgniteConfiguration.setSystemThreadPoolSize(...);
//By default it has size equals to max(8, total_no_of_cores)
Public thread pool
All computations are received by processed in this thread pool.
IgnitionConfiguration.setPublicThreadPoolSize(...);
//By default it has size equals to max(8, total_no_of_cores)
Queries pool
Handles the SQL queries and SCAN operation executed across the cluster.
IgnitionConfiguration.setQueryThreadPoolSize(...);
//By default it has size equals to max(8, total_no_of_cores)
Services Pool
Handles service-grid calls.
IgniteConfiguration.setServicePoolSize(...);
//By default it has size equals to max(8, total_no_of_cores)
Striped Pool
Accelerate basic caching operations and transactions by spreading execution on multiples stripes that don't contend with each other.
IgniteConfiguration.setStripedPoolSize(...);
//By default it has size equals to max(8, total_no_of_cores)
Data stream pool
Used in data streaming.
IgniteConfiguration.setDataStreamerPoolSize(...);
//By default it has size equals to max(8, total_no_of_cores)
Custom thread pool
You can define your own custom thread pools. These are used in compute grid. For example, you want to run another task from compute grid task and you also want to avoid the deadlocks. This could be done with custom thread pools synchronously.
IgniteConfiguration icfg = ...;
icfg.setExecutorConfiguration(new ExecutorConfiguration("myCustomThreadPool").setSize(16));
class InternalTask implements IgniteRunnable {
private static final long serialVersionUID = 5169676352276118235L;
@Override
public void run() {
System.out.println("Internal task executed!");
}
}
class OuterTask implements IgniteRunnable {
private static final long serialVersionUID = 602712410415356484L;
@IgniteInstanceResource
private Ignite ignite;
@Override
public void run() {
System.out.println("Ignite Outer task!");
ignite.compute().withExecutor("myCustomThreadPool").run(new InternalTask());
}
}
// Ignite main example class
IgniteConfiguration icfg = defaultIgniteCfg("custom-thread-pool-grid");
icfg.setExecutorConfiguration(new ExecutorConfiguration("myCustomThreadPool").setSize(16));
try (Ignite ignite = Ignition.start(icfg)) {
ignite.compute().run(new OuterTask());
}
Apache Ignite API comes with synchronous and asynchronous support. Asynchronous calls return IgniteFuture
or one of its implementations. You can call the blocking get method to get value or can add listener(IgniteInClosure
) which will get executed as soon as the IgniteFuture has the result.
IgniteCompute compute = ignite.compute();
IgniteFuture fut = compute.callAsync(() -> "Hello from Callable");
//blocking call
String result = fut.get();
//added listener to future which will get executed as soon as future has result.
fut.listener(f -> System.out.println(f.get());
If the IgniteFuture
is already have the result from asynchronous operation by the time IgniteInClosure
is passed to listen or chain method, then it will be executed synchronously with the caller thread. Otherwise closure will get executed when the asynchronous operation finishes. The closure will be called in system thread pool for asynchronous cache related operations or public thread pool in case of compute operations. So, it is recommended(at least avoid) calling cache/ compute related operations from the closure to avoid deadlocks due to thread starvations.
Ignite support dependency injection of pre-defined resources which could be used in the task, jo, closure or SPI. It supports both field and method based injection.
IgniteRunnable task = new IgniteRunnable() {
private static final long serialVersionUID = 787726700536869271L;
@IgniteInstanceResource
private transient Ignite ignite;
@Override
public void run() {
System.out.println("Hello Gaurav Bytes from: " + ignite.name());
}
};
In the above example code, we have used @IgniteInstanceResource
annotation to inject current Ignite
instance in the IgniteRunnable
object. There are other pre-defined resources that you can inject in the jobs, tasks, closures and SPI.
Resource Name | Description |
---|---|
@IgniteInstanceResource |
Injects current instance of Ignite API |
@CacheNameResource |
Injects the grid-cache name provided by the CacheConfiguration.getName() |
@CacheStoreSessionResource |
Injects the CacheStoreSession instance |
@LoadBalancerResource |
Injects the ComputeLoadBalancer instance for load-balancing |
@SpringApplicationContextResource |
Injects the Spring's ApplicationContext |
Apart from this, there are few other resources like TaskContinuousMapperResource
, TaskSessionResource
, SpringResource
, ServiceResource
and JobContextResource
.