This article covers a Bloomreach Experience Manager version 12. There's an updated version available that covers our most recent release.

Enable and Configure HST Enterprise Caching

This Bloomreach Experience Manager feature requires a standard or premium license. Please contact Bloomreach for more information.

Introduction

Goal

Enable and configure enterprise caching features in Hippo's delivery tier.

Background

Enterprise Caching makes the community edition's page caching much more powerful and efficient, and makes a delivery tier cluster work more efficiently by reusing cached pages between cluster nodes. In addition, it allows for domain-specific optimization through cluster-wide caching.

This page describes how to enable and configure Enterprise Caching features.

To learn how Enterprise Caching works and what its added value is over the community edition's caching features, see Understand HST Enterprise Caching.

To configure logging and monitor performance using JMX, see Monitor HST Enterprise Caching.

HST Enterprise Caching Features

Enterprise Caching comes with three different caches for the delivery tier:

  1. Stale Page Cache
  2. Second Level Page Cache
  3. Cluster-Wide Generic Cache

All three caches work independently from each other. Depending on your exact requirements, you can enable only those caches that you need.

Requirements

For the Stale Page Cache you do not need anything other than adding the enterprise caching add-on and enable the Stale Page Cache. For the Second Level Cache and Cluster-Wide Generic Cache you need to setup Redis. Note that in case of high availability requirements at this moment we only support Redis Clustering and not (yet) Redis Sentinel. The Redis (cluster) needs to be compatible with the jedis 2.9.0 client.

If your project is hosted in Bloomreach Cloud, it is currently not possible to use Second Level Cache or Cluster-Wide Generic Cache, because Redis is used for other internal purposes. See Restrictions and Limitations.

Add HST Enterprise Caching

To add enterprise caching to your implementation project, add the following dependency to site/pom.xml:

<dependency>
  <groupId>com.onehippo.cms7</groupId>
  <artifactId>hippo-addon-caching-hst</artifactId>
</dependency>

The above dependency pulls in all required jars. Note that including this dependency does not yet enable any of the caches. Below is described how to enable the different caches.

Enable Stale Page Caching

To enable Stale Page Caching, add to your HST webapp context.xml, typically located at:

/site/src/main/webapp/META-INF/context.xml

the following JNDI variable:

<Environment name="stalePageCache" type="java.lang.String" value=""/>

This enables Stale Page Caching with default configuration. If you'd like to tune some settings, the following attributes can be configured:

<Environment name="stalePageCache" type="java.lang.String"
                 value="{'maxEntriesLocalHeap' : 10000,
                 'maxEntriesLocalDisk' : 0,
                 'eternal' : false,
                 'timeToLiveSeconds' : 86400,
                 'timeToIdleSeconds' : 86400,
                 'diskExpiryThreadIntervalSeconds' : 120,
                 'stats' : true}" />

The above values are the same as the defaults.

With Stale Page Caching enabled, you might get to see a stale page result after you made a change to the content until the page has been recreated (fresh) by a request.

Enable Second Level Page Caching

To enable Second Level Page Caching, add to your HST webapp context.xml, typically located at:

site/src/main/webapp/META-INF/context.xml

the following JNDI variable:

<Environment name="secondLevelPageCache" type="java.lang.String" value=""/>

This enables Second Level Page Caching with default configuration. If you'd like to tune some settings, the following attributes can be configured:

<Environment name="secondLevelPageCache" type="java.lang.String"
                 value="{
                  'ttlSeconds':300,
                  'profiling' : true,
                  'stats' : true,
                  'quiet' : true,
                  'async' : true}" />

The above values are the same as the defaults. The attributes profiling, stats, quiet and async are optional and if not specified true by default. ttlSeconds is optional and, if not specified, 300 seconds. 

Explanation of the attributes:

  • profiling: If true, profiling information is exposed over JMX about how long puts and gets take 
  • stats: If true, statistics information is exposed over JMX of the cache like hits/misses/puts/ratios 
  • quiet: If true, you won't get an exception from the org.springframework.cache.Cache in case a put of get or any other method results in an exception (for example a timeout). If you have 'quiet' : false but 'async' : true (also the default), you won't get an exception thrown for puts because the put is done asynchronously. For a get you can get an exception from the backing cache. If you also have 'async' : false, then you're code will get the runtime exception from the backing cache if something fails for both put and get.
  • async: If true, all void methods on org.springframework.cache.Cache are done asynchronously, most notably the #put method. The big advantage is that when the put is done async, request processing is not blocked during storing entries in the Second Level Page Cache. 
With Second Level Page Caching it can take up to ttlSeconds before you can see your changes reflected in the live site. The preview in Channel Manager will directly reflect your changes.

Enable Cluster-Wide Generic Cache

To enable Cluster-Wide Generic Caching, you have to add to your HST webapp context.xml, for example in case your HST webapp is site at 

site/src/main/webapp/META-INF/context.xml

the following JNDI variable

<Environment name="clusterCache" type="java.lang.String" value=""/>

This enables Cluster-Wide Generic Caching with default configuration. If you'd like to tune some settings, the following attributes can be configured

<Environment name="clusterCache" type="java.lang.String"
                 value="{
                  'ttlSeconds':300,
                  'profiling' : true,
                  'stats' : true,
                  'quiet' : true,
                  'async' : true}" />

The above values are the same as the defaults. The attributes mean the same as above for the secondLevelPageCache.

Use Cluster-Wide Generic Cache

When the 'clusterCache' is configured, retrieving and using it in HST code can be done as follows:

HippoRedisCacheManager cacheManager = HstServices
                .getComponentManager()
                .getComponent(HippoRedisCacheManager.class.getName(), 
                              "com.onehippo.cms.spring.cache");
                  
Cache cache = cacheManager.getCache("clusterCache");

Visitor visitor = cache.get(visit_id, Visitor.class);
if (visitor == null) {
   visitor = expensiveGet(visit_id);
   cache.put(visit_id, visitor);
} 

In the example above, the Visitor object must be serializable.  If you have the cache configured as

'quiet' : true

 (which is the default if not configured) you won't get an exception thrown but just a warning log from QuietCache. If you have 'quiet' : false but 'async' : true (also the default), you won't get an exception thrown for puts because the put is done asynchronously. For a get you can get an exception from the backing cache. If you also have 'async' : false, then you're code will get the runtime exception from the backing cache if something fails for both put and get.

Configure the Redis Connection Settings

By default, the connection factory tries to connect to a Redis instance with 

hostname = localhost  
port 6379
connectionTimeoutMs = 1000
timeoutMs = 10

If you have configured Redis on a different server or port, or you want a different (connection) timeout, you can modify these defaults. Be careful not to make the timeoutMs much higher than 10 ms because it might result in taking too long lookups for cache key entries to be present (for storing it is less harmful since a Redis cache put happens asynchronously). Since latency needs to be very low, we recommend installing the redis nodes on the same servers as where the application runs so every container has local access to a Redis instance. If you'd like to change the defaults, you can do so as follows

In your local Cargo-based development environment, add a JNDI environment variable that contains configuration properties for connecting to Redis. Add the following JNDI environment variable to conf/context.xml:

<Environment name="redis/hippoJedisConnectionFactory" type="java.lang.String"
                 value="{'hostname':'localhost',
                 'port':6379,
                 'connectionTimeoutMs' : 1000,
                 'timeoutMs' : 10}" />

Note that the <Environment /> variable above should go into the global conf/context.xml whereas the specific Second Level Page Cache, Stale Page Cache and Generic Cluster-Wide Cache context configuration should go into the site webapp context.xml

Redis Cache Key Prefixing

If your Redis cache is being used my multiple applications, you might want to use cache key prefixing to avoid accidental cache key collisions. You can do so in the global container conf/context.xml by specifying the JNDI variables

<Environment name="env" type="java.lang.String" value="foo" />
<Environment name="stack" type="java.lang.String" value="bar"/>

Then the created Redis Cache Keys will be prefixed with <env>-<stack>:hippo:, thus for the example above, with 'foo-bar:hippo:'. This is useful if for example your redis instances are shared between different environments (test/acct/prod) or between different stacks (customers). 

Did you find this page helpful?
How could this documentation serve you better?
On this page
    Did you find this page helpful?
    How could this documentation serve you better?