Utilizing Hazelcast Cache - WSO2 Servers

With Caron 4.2.0 release WSO2 moved to Hazelcast from Apache Tribes. We have also introduced a new JSR-107 (JCache) caching implementation.

Features of WSO2 Caching


Internal caching implementation of WSO2 has three main features


  1. Local and distributed mode - If clustering is enabled cache work as a distributed cache. If not it works as a local cache. No code changes required. 
  2. L1 and L2 caching model for distributed mode - The L1 cache is implemented using HashMaps, and the L2 cache is implemented using Hazelcast distributed maps. As a result, first the L1 cache is checked, and if there is a cache miss, then the L2 cache is checked. If the value is located in the L2 cache, then the value is also stored it in the L1 cache.
  3. Multi-tenancy  - different tenants will have different caches working completely independently. This makes cache behavior  configurable tenant wise and improve data separation between tenants.

Distributed Caching

WSO2 uses Hazelcast Maps to implement distributed caching. This works as a distributed in-memory grid. L1 cache is implemented before Hazelcast layer to improve performance. Refer below diagram how message flow happens between caches. 




Using Distributed Caching for Web Applications 

If you use WSO2 Application Server to host the web applications, and if you have a cluster of WSO2 AS, then this feature might come in handy for certain requirements. 

  1. Minimize DB transactions - typically DB queries are costly. If there are same requests asking for same results into the web application, needlessly to say hitting the DB again and again will be a performance killer.  You can use WSO2 caching to overcome this. (If you are using services this is OOB available with service level caching). 
  2. Coordination required between nodes - Suppose when a request hit a DB, it generates a certain ID. When you have a Application Sever cluster, request will come to node1 and hit the DB and cache the response. If individual caches are used to cater this scenario, when the same next request come to node2, it will generate different ID hitting the DB and this will make an inconsistency. At such a situation, a distributed cache is a must.
  3. Ability to share same cache across multiple web applications - If individual web applications maintain their local caches in web application level, there might be a data duplication in memory if all web apps need to cache same responses. Also when web applications are hit, there will be more DB transactions than using a shared cache across web apps. 
  4. Ability to shut down a node, do a upgrade and restart. Then the local cache (L1) of that WSO2 server will not have the entry but the distributed cache (L2) will. It will fetch from the connected Hazlecast instances and put it into L1 cache without any DB transaction. 




WSO2 Caching API

Following code snippet can be used to implement above mentioned caching. Every entry on the cache will have configured TTL. 

import javax.cache.Cache;
import javax.cache.CacheConfiguration;
import javax.cache.CacheManager;
import javax.cache.Caching;
import java.util.concurrent.TimeUnit;

public class HazelcastCache {

    private static final String cacheName = "HAZELCAST_MEMORY_CACHE";
    private static final String cacheManagerName = "WSO2_CACHE_MANAGER";
    private static Cache cache = null;

    public static void init() {

        CacheManager cacheManager = Caching.getCacheManagerFactory().getCacheManager(
                cacheManagerName);
        cache = cacheManager.getCache(cacheName);
        if (null == cache) {
            cache = cacheManager
                    .createCacheBuilder(cacheName)
                    .setExpiry(
                            CacheConfiguration.ExpiryType.MODIFIED,
                            new CacheConfiguration.Duration(TimeUnit.MINUTES,
                                    10)).setStoreByValue(false).build();
        }
    }

    public static void write(String key, String value) {
        cache.put(key, value);
    }

    public static String read(String key) {
        String value = cache.get(key);
        return value;
    }
}


Following are the dependencies needed

<dependency>
    <groupId>javax.cache</groupId>
    <artifactId>cache-api</artifactId>
    <version>0.5</version>
    <scope>provided</scope>
</dependency>


A Sample Web Application 

You can clone the sample web application i have developed to demo the functionality here.

Testing the caching 

  1. Setup a WSO2 Application Server cluster following document - How to Cluster WSO2 AS
  2. Deploy the web application (built from above source) via the management node. It will be deployment synchronized to worker nodes. 
  3. Let us consider 2 different worker nodes. W1 will run with offset=1 ( port : 9764) and W2 will run with offset=2 (port : 9765). 
  4. Hit url http://127.0.0.1:9764/wso2cacheapp/ and add some key-value to the cache. 

  1. Hit url http://127.0.0.1:9765/wso2cacheapp/  and retrieve value using the key. You will get the value entered. This means cache is distributed. 



Hasitha Hiranya

No comments:

Post a Comment

Instagram