This section will show you how to use and configure Jboss Cache in the clustered environment. Also, you will know how to use a template-based configuration offered by JCR for JBoss Cache instances.
For indexer, lock manager and data container
Each mentioned component uses instances of JBoss Cache product for caching in clustered environment. So every element has its own transport and has to be configured in a proper way. As usual, workspaces have similar configuration but with different cluster-names and maybe some other parameters. The simplest way to configure them is to define their own configuration files for each component in each workspace:
<property name="jbosscache-configuration" value="${gatein.jcr.index.cache.config}"/>
However, if there are few workspaces, configuring them in such a way can
be painful and hard to manage JCR which offers a template-based configuration for JBoss Cache instances. You can have one template for
Lock Manager, one for Indexer and one for data container and use them in
all the workspaces, defining the map of substitution parameters in a main
configuration file. Just simply define ${jbosscache-<parameter
name>}
inside xml-template
and list correct values in the JCR configuration
file just below "jbosscache-configuration
", as shown:
Template:
...
<clustering mode="replication" clusterName="${jbosscache-cluster-name}">
<stateRetrieval timeout="20000" fetchInMemoryState="false" />
...
JCR configuration file:
...
<property name="jbosscache-configuration" value="${gatein.jcr.lock.cache.config}" />
<property name="jbosscache-cluster-name" value="${gatein.jcr.jgroups.config}" />
...
JGroups is used by JBoss Cache for network communications and transport in a clustered environment. If property "jgroups-configuration" is defined in component configuration, it will be injected into the JBoss Cache instance on startup.
<property name="jgroups-configuration" value="${gatein.jcr.jgroups.config}" />
As mentioned above, each component (lock manager, data container and query handler) for each workspace requires its own clustered environment. In other words, they have their own clusters with unique names. By default, each cluster should perform multi-casts on a separate port. This configuration leads to much unnecessary overhead on cluster. That is why JGroups offers multiplexer feature, providing the ability to use one single channel for a set of clusters. This feature reduces network overheads and increase performance and stability of application.
To enable multiplexer
stack, you should define appropriate configuration file (upd-mux.xml
is
pre-shipped one with JCR) and set "jgroups-multiplexer-stack
" to
"true".
<property name="jgroups-configuration" value="jar:/conf/portal/udp-mux.xml" />
<property name="jgroups-multiplexer-stack" value="true" />
It is now highly recommended to use the shared transport instead of the multiplexer. To do so, simply disable the multiplexer stack in the configuration of each component by setting the property jgroups-multiplexer-stack to "false" then you will need to ensure that the format of your jgroups configuration is not anymore a jgroups stack definitions but a normal configuration. Finally, you will need to set the property singleton_name of your JGroups configuration to a unique name (this name must not be the same from one portal container to another).
<property name="jgroups-configuration" value="jar:/conf/portal/udp-mux.xml" />
<property name="jgroups-multiplexer-stack" value="false" />
Allow sharing JBoss Cache instances
A JBoss Cache instance is quite resource consuming and there are three JBoss Cache instances by default (one instance for the indexer, one for the lock manager and one for the data container) for each workspace, so if you intend to have a lot of workspaces, it could make sense to decide to share one JBoss Cache instance with several cache instances of the same type (for example: indexer, lock manager or data container). This feature is disabled by default and can be enabled at component configuration level (for example: indexer configuration, lock manager configuration and/or data container configuration) by setting the property "jbosscache-shareable" to "true" as below:
<property name="jbosscache-shareable" value="true" />
Once enabled, this feature will allow the JBoss Cache instance used by the component to be re-used by another components of the same type (for example: indexer, lock manager or data container) with the same JBoss Cache configuration (except the eviction configuration that can be different). This means all the parameters of type ${jbosscache-<parameter name>} must be identical between the components of same type of different workspaces. In other words, if you use the same values for the parameters of type ${jbosscache-<parameter name>} in each workspace, you will have only 3 JBoss Cache instances (one instance for the indexer, one for the lock manager and one for the data container) used whatever the total amount of workspaces defined.
Configure the maximum invalidations
In clustered environment, jbosscache-max-invalidations
parameter is used by
JBossCacheWorkspaceStorageCache
to indicate the maximum total amount of invalidation operations that can be done
outside the current transaction in auto commit mode to prevent potential deadlocks.
This parameter is dedicated to cluster mode only and is needed to ensure that even with
big transactions that do a lot of invalidations, there will not be too many JGroups calls
that can dramatically affect the scalability and the performance of the whole platform.
The value should be big enough to prevent deadlocks on operations that concurrently
add/remove JCR nodes to/from the same parent node, but in contrast, setting it too big
will affect the scalability and the performance. The default value is 10
.
This parameter can be configured at cache configuration as below:
<property name="jbosscache-max-invalidations" value="20" />
Shipped JBoss Cache configuration templates
JCR implementation is shipped with ready-to-use JBoss Cache configuration templates for JCR's components. They are situated in application package in /conf/porta/ folder.
Data container template: The Data container template is in jbosscache-data.xml
.
<?xml version="1.0" encoding="UTF-8"?>
<jbosscache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:jboss:jbosscache-core:config:3.1">
<locking useLockStriping="false" concurrencyLevel="500" lockParentForChildInsertRemove="false"
lockAcquisitionTimeout="20000" />
<clustering mode="replication" clusterName="${jbosscache-cluster-name}">
<stateRetrieval timeout="20000" fetchInMemoryState="false" />
<sync />
</clustering>
<!-- Eviction configuration -->
<eviction wakeUpInterval="5000">
<default algorithmClass="org.jboss.cache.eviction.ExpirationAlgorithm"
actionPolicyClass="org.exoplatform.services.jcr.impl.dataflow.persistent.jbosscache.ParentNodeEvictionActionPolicy"
eventQueueSize="1000000">
<property name="maxNodes" value="1000000" />
<property name="warnNoExpirationKey" value="false" />
</default>
</eviction>
</jbosscache>
Lock manager template: The Lock manager template name is in jbosscache-lock.xml
.
<?xml version="1.0" encoding="UTF-8"?>
<jbosscache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:jboss:jbosscache-core:config:3.1">
<locking useLockStriping="false" concurrencyLevel="500" lockParentForChildInsertRemove="false"
lockAcquisitionTimeout="20000" />
<clustering mode="replication" clusterName="${jbosscache-cluster-name}">
<stateRetrieval timeout="20000" fetchInMemoryState="false" />
<sync />
</clustering>
<loaders passivation="false" shared="true">
<preload>
<node fqn="/" />
</preload>
<loader class="org.exoplatform.services.jcr.impl.core.lock.jbosscache.JDBCCacheLoader" async="false" fetchPersistentState="false"
ignoreModifications="false" purgeOnStartup="false">
<properties>
cache.jdbc.table.name=${jbosscache-cl-cache.jdbc.table.name}
cache.jdbc.table.create=${jbosscache-cl-cache.jdbc.table.create}
cache.jdbc.table.drop=${jbosscache-cl-cache.jdbc.table.drop}
cache.jdbc.table.primarykey=${jbosscache-cl-cache.jdbc.table.primarykey}
cache.jdbc.fqn.column=${jbosscache-cl-cache.jdbc.fqn.column}
cache.jdbc.fqn.type=${jbosscache-cl-cache.jdbc.fqn.type}
cache.jdbc.node.column=${jbosscache-cl-cache.jdbc.node.column}
cache.jdbc.node.type=${jbosscache-cl-cache.jdbc.node.type}
cache.jdbc.parent.column=${jbosscache-cl-cache.jdbc.parent.column}
cache.jdbc.datasource=${jbosscache-cl-cache.jdbc.datasource}
</properties>
</loader>
</loaders>
</jbosscache>
To prevent any consistency issue regarding the lock data, ensure that your cache loader is org.exoplatform.services.jcr.impl.core.lock.jbosscache.JDBCCacheLoader and your database engine is transactional.
Query handler (indexer) template
Have a look at jbosscache-indexer.xml
<?xml version="1.0" encoding="UTF-8"?>
<jbosscache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:jboss:jbosscache-core:config:3.1">
<locking useLockStriping="false" concurrencyLevel="500" lockParentForChildInsertRemove="false"
lockAcquisitionTimeout="20000" />
<clustering mode="replication" clusterName="${jbosscache-cluster-name}">
<stateRetrieval timeout="20000" fetchInMemoryState="false" />
<sync />
</clustering>
</jbosscache>
To learn about the properties, see their corresponding descriptions in Configuring JCR in cluster.