6. Caching
Caching in a cloud environment is useful for applications to reduce the latency and to save database round trips. Reducing database round trips can significantly reduce the requirements for the database instance. The Spring Framework provides, since version 3.1, a unified Cache abstraction to allow declarative caching in applications analogous to the declarative transactions.
Spring Cloud AWS integrates the Amazon ElastiCache service into the Spring unified caching abstraction providing a cache manager based on the memcached and Redis protocols. The caching support for Spring Cloud AWS provides its own memcached implementation for ElastiCache and uses Spring Data Redis for Redis caches.
6.1. Configuring dependencies for Redis caches
Spring Cloud AWS delivers its own implementation of a memcached cache, therefore no other dependencies are needed. For Redis Spring Cloud AWS relies on Spring Data Redis to support caching and also to allow multiple Redis drivers to be used. Spring Cloud AWS supports all Redis drivers that Spring Data Redis supports (currently Jedis, JRedis, SRP and Lettuce) with Jedis being used internally for testing against ElastiCache. A dependency definition for Redis with Jedis is shown in the example
<dependencies>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>${spring-data-redis.version}</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.6.1</version>
</dependency>
</dependencies>
Spring Cloud AWS will automatically detect the Redis driver and will use one of them automatically.
6.2. Configuring caching with XML
The cache support for Spring Cloud AWS resides in the context module and can therefore be used if the context module is already imported in the project. The cache integration provides its own namespace to configure cache clusters that are hosted in the Amazon ElastiCache service. The next example contains a configuration for the cache cluster and the Spring configuration to enable declarative, annotation-based caching.
<beans xmlns:aws-cache="http://www.springframework.org/schema/cloud/aws/cache"
xmlns:cache="http://www.springframework.org/schema/cache"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/cloud/aws/cache
http://www.springframework.org/schema/cloud/aws/cache/spring-cloud-aws-cache.xsd
http://www.springframework.org/schema/cache
https://www.springframework.org/schema/cache/spring-cache.xsd">
<aws-context:context-credentials>
...
</aws-context:context-credentials>
<aws-cache:cache-manager>
<aws-cache:cache-cluster name="CacheCluster" />
</aws-cache:cache-manager>
<cache:annotation-driven />
</beans>
The configuration above configures a cache-manager
with one cache with the name CacheCluster
that represents an
ElasticCache cluster.
6.2.1. Mixing caches
Applications may have the need for multiple caches that are maintained by one central cache cluster. The Spring Cloud AWS caching support allows to define multiple caches inside one cache manager and also to use externally defined caches inside the cache manager.
The example below demonstrates a configuration example that contains a pre-configured cache with a cache-ref
element
(which might be a local cache) and a cache-cluster
configuration for ElastiCache cache clusters.
<beans ...>
<aws-cache:cache-manager id="cacheManager">
<aws-cache:cache-ref ref="memcached" />
<aws-cache:cache-cluster name="SimpleCache"/>
</aws-cache:cache-manager>
</beans>
6.2.2. Defining expiration
The Spring cache demarcation does not support expiry time configuration and leaves it up to the cache implementation to support an expiry time. The Spring Cloud AWS cache configuration supports the expiry time setting per cache. The expiry time will be passed to the memcached service.
The cache-cluster
element accepts an expiration attribute that defines the expiration time in seconds.
No configured values implies that there is an infinite expiration time.
<beans>
<aws-cache:cache-manager>
<aws-cache:cache-cluster expiration="10000" name="CacheCluster" />
</aws-cache:cache-manager>
</beans>
6.3. Configuring caching using Java configuration
Spring Cloud AWS also support the cache configuration with Java configuration classes. On any Configuration
class,
the caching can be configured using the org.springframework.cloud.aws.cache.config.annotation.EnableElastiCache
annotation provided by Spring Cloud AWS. The next example shows a configuration of two cache clusters.
@EnableElastiCache({@CacheClusterConfig(name = "firstCache"), @CacheClusterConfig(name = "secondCache")})
public class ApplicationConfiguration {
}
If you leave the value attribute empty, then all the caches inside your CloudFormation stack (if available)
will be configured automatically.
|
6.3.1. Configuring expiry time for caches
The Java configuration also allows to configure the expiry time for the caches. This can be done for all
caches using the defaultExpiration
attribute as shown in the example below.
@EnableElastiCache(defaultExpiration = 23)
public class ApplicationConfiguration {
}
The expiration can be defined on a cache level using the @CacheClusterConfig
annotations expiration attribute as shown below (using seconds as
the value).
@EnableElastiCache({@CacheClusterConfig(name = "firstCache", expiration = 23), @CacheClusterConfig(name = "secondCache", expiration = 42)})
public class ApplicationConfiguration {
}
6.4. Configuring caching in Spring Boot
The caches will automatically be configured in Spring Boot without any explicit configuration property.
6.5. Using caching
Based on the configuration of the cache, developers can annotate their methods to use the caching for method return values. The next example contains a caching declaration for a service for which the return values should be cached
@Service
public class ExpensiveService {
@Cacheable("CacheCluster")
public String calculateExpensiveValue(String key) {
...
}
}
6.6. Memcached client implementation
There are different memcached client implementations available for Java, the most prominent ones are Spymemcached and XMemcached. Amazon AWS supports a dynamic configuration and delivers an enhanced memcached client based on Spymemcached to support the auto-discovery of new nodes based on a central configuration endpoint.
Spring Cloud AWS relies on the Amazon ElastiCache Client implementation and therefore has a dependency on that.
6.7. Using CloudFormation
Amazon ElastiCache clusters can also be configured within a stack and then be used by applications. Spring Cloud AWS also supports the lookup of stack-configured cache clusters by their logical name with the resolution to the physical name. The example below shows a cache cluster configuration inside a CloudFormation template.
"CacheCluster": {
"Type": "AWS::ElastiCache::CacheCluster",
"Properties": {
"AutoMinorVersionUpgrade": "true",
"Engine": "memcached",
"CacheNodeType": "cache.t2.micro",
"CacheSubnetGroupName" : "sample",
"NumCacheNodes": "1",
"VpcSecurityGroupIds": ["sample1"]
}
}
The cache cluster can then be used with the name CacheCluster
inside the application configuration as shown below:
<beans...>
<aws-cache:cache-manager>
<aws-cache:cache-cluster name="CacheCluster" expiration="15"/>
</aws-cache:cache-manager>
<beans>
With the configuration above the application can be deployed with multiple stacks on different environments without any configuration change inside the application.