Wired For Code

Groovy, Grails and Griffon on Linux.

Grails on Terracotta Using Ehcache

These days, much talk goes into making your applications scale better. With the internet growing rapidly, and large companies investing vast sums of money into presenting their goods to the world, we need to become more innovative in how we handle these large volumes of traffic. Somehow, our single small instance of Tomcat fronted by a little Apache just won’t cut it any more!

So how do you go about scaling an application out? More specifically, how do you scale a Grails application? In the Java landscape we have several great clustering technologies to choose from. The product that I tend to levitate towards is the open source Terracotta. This is a practical guide to scaling out a Grails application with Terracotta using Ehcache integration.

Configure your Application

Firstly, we need to get our application ready for working with Terracotta. As expected, Terracotta (almost) doesn’t impose on your code. Here’s how I got it all working:

Step 1: Implement Serializable All domain classes should implement java.io.Serializable. There is no need to import it because it’s already provided by Groovy!

1
2
3
4
5
6
7
package my.app
class Person implements Serializable {
    String firstName
    String lastName
    static constraints = {
    }
}

Step 2: Make Domain Classes Cacheable All domain classes to be clustered should be marked as cacheable in the mapping closure of the class.

1
2
3
4
5
6
class Person implements Serializable {
    ...
    static mapping = {
        cache true
    }
}

Step 3: Add the Terracotta Maven Repository This is done in the BuildConfig.groovy file. Locate the repositories section and update the following:

1
2
3
4
5
6
7
8
repositories {
    ...
    //uncomment mavenCentral
    mavenCentral()
    ...
    //add terracotta repos
    mavenRepo http://www.terracotta.org/download/reflector/releases”
}

Step 4: Introduce the Ehcache and Terracotta Dependencies This can be done easily using the dependency resolution DSL in the grails-app/conf/BuildConfig.groovy file. Find the inherits("global") section and update as follows:

1
2
3
4
5
6
7
8
inherits(global) {
    // uncomment to disable ehcache
    // excludes ‘ehcache’
    runtime net.sf.ehcache:ehcache-core:2.4.2
    runtime net.sf.ehcache:ehcache-terracotta:2.4.2
    runtime org.terracotta:terracotta-toolkit-1.2-runtime:3.1.0
    ...
}

Step 5: Configure Ehcache to use Terracotta Create a file called ehcache.xml in the grails-app/conf folder. This will create an Ehcache CacheManager called MyCache, and will give you some defaults to begin working with. Refer to the ehcache website to add cache configurations per Domain class in your app.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="UTF-8"?>
<ehcache name="MyCache"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:noNamespaceSchemaLocation="ehcache.xsd">

   <defaultCache
      maxElementsInMemory="1000"
      eternal="false"
      overflowToDisk="false"
      diskPersistent="false"
      timeToIdleSeconds="1200"
      timeToLiveSeconds="1200">
          <terracotta />
   </defaultCache>

   <terracottaConfig url="localhost:9510" />

</ehcache>

The import things to look out for are the terracotta tags in this file. The first lies within the defaultCache tags, and marks it to be clustered by Terracotta. The second lies within the ehcache tags, and specifies where to find the terracotta server. More about that in a minute…

Step 6: Add a Custom Cache Configuration Next, we will add a cutom cache config for our Person class. This is simply done by adding a set of cache tags to the ehcache.xml file right beneath the defaultCache tags.

1
2
3
4
5
6
7
8
9
10
11
  <defaultCache>
  ...
  </defaultCache>

  <!-- Add the custom cache config here -->
  <cache name="my.app.Person" maxElementsInMemory="1000"
      maxElementsOnDisk="10000" eternal="false" timeToIdleSeconds="3600"
      timeToLiveSeconds="0" memoryStoreEvictionPolicy="LFU">
      <!-- Adding this element turns on clustering for myCache. -->
      <terracotta />
  </cache>

One final thing…

It’s very important to use a persistent database for this exercise to succeed. We will need to open our grails-app/conf/DataSource.groovy file and update it as follows, using the HSQLDB file database, in update dbCreate mode.

1
2
3
4
5
6
7
8
9
10
...
environments {
    development {
        dataSource {
            dbCreate = "update" // one of 'create', 'create-drop','update'
            url = "jdbc:hsqldb:file:devDB"
        }
    }
    test {
...

Let’s have some fun!!!

That’s it. Most of the hard work is done, and we are now ready to start testing our clustered Grails app!

Let’s head on over to the Terracotta Site and download the Terracotta Binary Distribution. Unpack it to a convenient place (usually in /usr/local) and start up the server in a terminal. $ /usr/local/terracotta-3.3.0/bin/start-tc-server.sh

Next, fire up the Terracotta dev console: $ /usr/local/terracotta-3.3.0/bin /dev-console.sh

You can now start your grails app, and should see it connecting to the terracotta server running locally. Click on the Ehcache button and select the Statistics tab. This should pop up a confirmation, answer yes to this. I created a few People using the scaffolding in Grails:

I then refreshed the Person List page in the browser MANY times in order to get the result below. As you can see, I had a 99% hit ratio!

Now for the fun bit! Stop and start your Grails app! Once it’s started up and connected to Terracotta again, try refreshing the Person List page and watch what the console has to say (remember to click refresh on the console): No misses and several hits! 100% Hit ratio, with NO database access!

Well, that’s it in a nutshell! Terracotta and Grails, one happy couple. In a subsequent post, I will write about setting up a cluster of Grails apps with several Terracotta servers. You will see that running a cluster is as easy as setting up a single instance like we did in this post.

Let me know your thoughts, and please share any other experiences you might have. Enjoy it and have lots of fun, Cheers, Marco.

Source Code of the above example is available here.

Comments