Liferay will support our API and resolve any issues and answer any questions having to do with the API itself or any other part of Liferay's software. Issues and questions regarding custom development may be handled by our Global Services team or by the developer of those customizations.
Many plugins need to be able to communicate over a cluster. While nodes in a cluster normally share a single database that can be used, it is often desirable to transmit messages to update in memory caches on other nodes or to tell all the nodes to take some action in response to a user's actions.
This article documents basic information on three ways to transit data across a cluster:
The MultiVMPoolUtil can be used to create and fetch portal caches, these caches are basically maps that can be shared across the cluster, or used on a single node. To create/fetch a portal cache simply call:
PortalCache portalCache = MultiVMPoolUtil.getCache("MarkAppCache");
portalCache.put("First key", "First Value");
*Portal caches can be used much like a map (the key and value does not have to be a String, that's just what I'm using for the example):
These values can then be retrieved later, but even better we allow designating a listener on the portal cache like so:
CacheListener<String, String> myCacheListener = new MyCacheListenerImpl<String, String>();
These caches can be configured to allow data to be sent across different nodes in a cluster.
<cache eternal="false" maxElementsInMemory="100" name="TestCache" overflowToDisk="false" timeToIdleSeconds="600" > <cacheEventListenerFactory class="com.liferay.portal.cache.ehcache.LiferayCacheEventListenerFactory" properties="replicatePuts=true,replicatePutsViaCopy=true,replicateUpdatesViaCopy=true" propertySeparator="," /> <bootstrapCacheLoaderFactory class="com.liferay.portal.cache.ehcache.LiferayBootstrapCacheLoaderFactory" /> </cache>
This would be in a file indicated by the
The root for this location for Tomcat is: tomcat-home/webapps/ROOT/WEB-INF/classes.
It's important to note that the properties replicatePutsViaCopy and replicateUpdatesViaCopy have a default of false for performance reasons. The max size of the cache is indicated by maxElementsInMemory. When this cap is reached a registered cache listener can react to the eviction.
ehcache.multi.vm.config.location is not just about setting up a caches to propagate across the cluster, it also directly changes all of Liferay's caches - this can be essential for performance tuning, so make sure to bring over elements from the default file and tune them for your specific environment (usually this involves increasing/decreasing cache sizes).
2. Clusterable Annotation
Liferay's Clusterable annotation is simple to implement and is used by the ClusterableAdvice:
@Clusterable (acceptor = MyClusterInvokeAcceptor.class, onMaster = true)
public void myMethod(Args args)
The cluster acceptor can implement the ClusterInvokeAcceptor which only has one method which determines if the annotated method will be fired on the node. Setting onMaster to true means only the master node will have this method called.
The ClusterExecuterUtil can be used when more fine grain handling needs to be done or when needing to do this outside of a service. This not as convenient as the annotation, it can only call static methods and all the arguments must be serializable.
First we need to create a method key:
MethodKey myMethodKey = new MethodKey(MethodClass.class, "methodName", FirstSerializableArguement.class ...);
Next we create the method handler:
MethodHandler myMethodHandler = new MethodHandler(myMethodKey, myFirstArguement....);
Now we can create the cluster request (having a true skipLocal parameter allows us to skip the current node):
ClusterRequest clusterRequest = ClusterRequest.createMulticastRequest(methodHandler, true);
This allows us to call methods outside of services.