Service Example
Define and deploy your own service.
This is a legacy Apache Ignite documentationThe new documentation is hosted here: https://ignite.apache.org/docs/latest/
Define Your Service Interface
As an example, let's define a simple counter service as a MyCounterService interface. Note that this is a simple Java interface without any special annotations or methods.
public interface MyCounterService {
/**
* Increment counter value and return the new value.
*/
int increment() throws CacheException;
/**
* Get current counter value.
*/
int get() throws CacheException;
}Service Implementation
An implementation of a distributed service has to implement both, Service and MyCounterService interfaces.
We implement our counter service by storing the counter value in cache. The key for this counter value is the name of the service. This allows us to reuse the same cache for multiple instances of the counter service.
public class MyCounterServiceImpl implements Service, MyCounterService {
/** Auto-injected instance of Ignite. */
@IgniteInstanceResource
private Ignite ignite;
/** Distributed cache used to store counters. */
private IgniteCache<String, Integer> cache;
/** Service name. */
private String svcName;
/**
* Service initialization.
*/
@Override public void init(ServiceContext ctx) {
// Pre-configured cache to store counters.
cache = ignite.cache("myCounterCache");
svcName = ctx.name();
System.out.println("Service was initialized: " + svcName);
}
/**
* Cancel this service.
*/
@Override public void cancel(ServiceContext ctx) {
// Remove counter from cache.
cache.remove(svcName);
System.out.println("Service was cancelled: " + svcName);
}
/**
* Start service execution.
*/
@Override public void execute(ServiceContext ctx) {
// Since our service is simply represented by a counter
// value stored in cache, there is nothing we need
// to do in order to start it up.
System.out.println("Executing distributed service: " + svcName);
}
@Override public int get() throws CacheException {
Integer i = cache.get(svcName);
return i == null ? 0 : i;
}
@Override public int increment() throws CacheException {
return cache.invoke(svcName, new CounterEntryProcessor());
}
/**
* Entry processor which atomically increments value currently stored in cache.
*/
private static class CounterEntryProcessor implements EntryProcessor<String, Integer, Integer> {
@Override public Integer process(MutableEntry<String, Integer> e, Object... args) {
int newVal = e.exists() ? e.getValue() + 1 : 1;
// Update cache.
e.setValue(newVal);
return newVal;
}
}
}Service Deployment
We should deploy our counter service as per-node-singleton within the cluster group that has our cache "myCounterCache" deployed.
// Cluster group which includes all caching nodes.
ClusterGroup cacheGrp = ignite.cluster().forCacheNodes("myCounterService");
// Get an instance of IgniteServices for the cluster group.
IgniteServices svcs = ignite.services(cacheGrp);
// Deploy per-node singleton. An instance of the service
// will be deployed on every node within the cluster group.
svcs.deployNodeSingleton("myCounterService", new MyCounterServiceImpl());Service Proxy
You can access an instance of the deployed service from any node within the cluster. If the service is deployed on that node, then the locally deployed instance will be returned. Otherwise, if service is not locally available, a remote proxy for the service will be created automatically.
Sticky vs Not-Sticky Proxies
Proxies can be either sticky or not. If proxy is sticky, then Ignite will always go back to the same cluster node to contact a remotely deployed service. If proxy is not-sticky, then Ignite will load balance remote service proxy invocations among all cluster nodes on which the service is deployed.
// Get service proxy for the deployed service.
MyCounterService cntrSvc = ignite.services().
serviceProxy("myCounterService", MyCounterService.class, /*not-sticky*/false);
// Ivoke a method on 'MyCounterService' interface.
cntrSvc.increment();
// Print latest counter value from our counter service.
System.out.println("Incremented value : " + cntrSvc.get());Access Service from Computations
For convenience, you can inject an instance of service proxy into your computation using @ServiceResource annotation.
IgniteCompute compute = ignite.compute();
compute.run(new IgniteRunnable() {
@ServiceResource(serviceName = "myCounterService");
private MyCounterService counterSvc;
public void run() {
// Ivoke a method on 'MyCounterService' interface.
int newValue = cntrSvc.increment();
// Print latest counter value from our counter service.
System.out.println("Incremented value : " + newValue);
}
});
