Chris Richardson - enterprise POJOs

My book

Calendar

««Aug 2008»»
SMTWTFS
      12
3456789
10111213141516
17181920212223
24252627282930
31

My Top Tags

                                                                               

My RSS Feeds








 

I run a consulting and training company that helps organizations build better software faster.

We provide a variety of services including:

  • Development - we can build your application for you
  • Deployment - we can find a hosting partner or deploy your application on Amazon EC2
  • Training classes for Spring, Hibernate and Acegi Security
  • Jumpstarts to get your project off to the right start
  • Reviews to improve your architecture, code and development process

For more information contact me.

 

My bookmarks

Mailing List

Running Java EE applications on Amazon EC2: deploying to 20 machines with no money down

posted Monday, 7 January 2008

Computer hardware has traditionally been a scarce, expensive resource. In the early days of computing developers had to share a single machine. Today each developer usually has their own machine but it’s rare for a developer to have more than one. This means that running performance tests often involves scavenging for machines.  Likewise, replicating even just part of a production environment is a major undertaking. With Amazon’s Elastic Compute Cloud (EC2), however, things are very different. A set of Linux servers is now just a web service call away. Depending on the type of the servers you simply pay 10-80 cents per server per hour for up to 20 servers! No more upfront costs or waiting for machines to be purchased and configured.

To make it easier for enterprise Java developers to use EC2, I have created EC2Deploy.  It’s a Groovy framework for deploying an enterprise Java application on a set of Amazon EC2 servers. EC2Deploy provides a simple, easy to use API for launching a set of EC2 instances; configuring MySQL, Apache and one or more Tomcat servers; and deploying one or more web applications. In addition, it can also run JMeter and collect performance metrics.

Here is an example script that launches some EC2 instances; configures MySQL with one slave, Tomcat and Apache; deploys a single web application on the Tomcat server; and runs a JMeter test with first one thread and then two.

class ClusterTest extends GroovyTestCase {
  void testSomething() {
    AWSProperties awsProperties = new 
        AWSProperties("/…/aws.properties")
    
    def ec2 = new EC2(awsProperties)
 
    def explodedWar = '…/projecttrack/webapp/target/ptrack'
 
    ClusterSpec clusterSpec = 
       new ClusterSpec()
            .schema("ptrack", ["ptrack": "ptrack"], 
                    ["src/test/resources/testdml1.sql", 
                     "src/test/resources/testdml2.sql"])
            .slaves(1)                  
            .tomcats(1)
            .webApp(explodedWar, "ptrack")
            .catalinaOptsBuilder({builder, databasePrivateDnsName ->
                 builder.arg("-Xmx500m")
                 builder.prop("com.sun.management.jmxremote")
                 builder.prop("com.sun.management.jmxremote.port", 8091)
                 builder.prop("com.sun.management.jmxremote.authenticate",             
                                     false)
                 builder.prop("com.sun.management.jmxremote.ssl", false)
                 builder.prop("ptrack.application.environment", "ec2")
                 builder.prop("log4j.configuration", 
                               "log4j-minimal.properties")
                 builder.prop("jdbc.db.server", databasePrivateDnsName)})
 
    SimpleCluster cluster = new SimpleCluster(ec2, clusterSpec)
 
    cluster.loadTest("…/projecttrack/functionalTests/jmeter/SimpleTest.jmx",
        [1, 2])
     
    cluster.stop()
  }
}

 

Let’s look at each of the pieces.

First, we need to configure the framework as follows:

    AWSProperties awsProperties = new 
        AWSProperties("/…/aws.properties")
    def ec2 = new EC2(awsProperties)

 

The aws.properties file contains various properties including the Amazon WS security credentials and the EC2 AMI (i.e. OS image) to launch. All servers use my EC2 appliance AMI that has Java, MySQL, Apache, Tomcat, Jmeter and some other useful tools pre-installed.

Next we need to configure the servers:

     ClusterSpec clusterSpec = 
        new ClusterSpec()
             .schema("ptrack", ["ptrack": "ptrack"], 
                    ["src/test/resources/testdml1.sql", 
                     "src/test/resources/testdml2.sql"])
             .slaves(1)                  
             .tomcats(1)
             .webApp(explodedWar, "ptrack")
             .catalinaOptsBuilder({builder, databasePrivateDnsName ->
                 builder.arg("-Xmx500m")
                 builder.prop("com.sun.management.jmxremote")
                 builder.prop("com.sun.management.jmxremote.port", 8091)
                 builder.prop("com.sun.management.jmxremote.authenticate",             
                                     false)
                 builder.prop("com.sun.management.jmxremote.ssl", false)
                 builder.prop("ptrack.application.environment", "ec2")
                 builder.prop("log4j.configuration", 
                               "log4j-minimal.properties")
                 builder.prop("jdbc.db.server", databasePrivateDnsName)})
 
     SimpleCluster cluster = new SimpleCluster(ec2, clusterSpec) 

This code first creates a ClusterSpec, which defines the configuration of the machines and the applications:

  • schema() – specifies the name of the database schema to create; names of the users and their passwords; the DML scripts to execute once the database has been create
  • slaves() – specifies how many MySql slaves to create
  • tomcats() - specifies how many Tomcats to run.
  • webApp() - configures a web application. This method takes two parameters: the path to the exploded WAR directory (conveniently created by Maven) and the context to deploy the web application under.
  • catalinaOptsBuilder() – supplies a closure that takes a builder and the DNS name of the MySQL server as arguments and returns the CATALINA_OPTS used to launch Tomcat. It’s primary purpose is to configure the web application(s) to use the correct database server

 It then creates a cluster with that specification.

We then start the cluster:

    cluster.start()

At this point EC2Deploy will:

1.       Launch the EC2 instances running my appliance AMI.

2.       Initialize the MySql master database

3.       Create the MySql slave

4.       Create the database schema and the users

5.       Run any DML scripts (these are cached on S3 in a bucket called “tmp-<schemaName>-dml” for the reasons described next)

6.       Upload the web applications to Amazon S3 (Simple Storage Service) where they are cached in order to avoid time consuming uploads (over slow DSL connections, for example). EC2Deploy only uploads new and changed files, which means that the bulky 3rd party libraries are only uploaded once. Each web application is stored in an S3 bucket called <context>-tmp-war. If this bucket does not exist you will see some warning messages and the bucket will be created.

7.       Deploy the web applications on each of the Tomcat servers

8.       Configure Apache to load balance across the Tomcat servers

 Once the cluster is started we can run a JMeter load test:

    cluster.loadTest("…/projecttrack/functionalTests/jmeter/SimpleTest.jmx", [1, 2])

The first argument specifies the test to run and the second argument is a list of JMeter thread counts. In this example, EC2deploy first runs the load test with one thread and then two threads. For each test run, it generates a report describing CPU utilization for each machine, average response time and throughput.

Finally, we stop the EC2 instances:

    cluster.stop()

As you can see, EC2Deploy makes it pretty easy to deploy and test your enterprise Java application. I’ve used it to clone a production environment and run load tests. NOTE 1/28/08: The source code EC2Deploy along with a very cool Maven plugin is now available !

 

tags:                          

links: digg this    del.icio.us    technorati    reddit




1. Jim LoVerde left...
Tuesday, 8 January 2008 12:20 pm

Very interesting.

Is your EC2Deploy framework open source? And if so, where can it be found?

Also, it would be really cool if this were packaged as a Grails plugin so that deploying to EC2 would be as simple as installing this plugin, editing the EC2Deploy config file(s), and running a grails target to deploy to EC2.


2. likesecc left...
Wednesday, 9 January 2008 8:50 am

You mentioned 10cents per 20 cpu hour. I don't see such cheap rate on Amazon EC2 site, it talks about 10cents per instance hour (which is not cpu hour). Anyway, can you clarify it?


3. Chris Richardson left...
Wednesday, 9 January 2008 11:11 am

I've clarify the wording in my blog entry that describes the pricing.


4. Chris Richardson left...
Wednesday, 9 January 2008 11:15 am

Jim,

I am planning to opensource the code shortly. I am in the middle of getting it ready for release. If you want to try it out right now please email me.

The idea of a Grails plugin is very interesting. I will give it some thought.

Chris


5. TheT left...
Thursday, 10 January 2008 2:22 am

EC2Deploy looks promising, is it meant just for easy development and testing support, because this would be really cool also for production deployment. But I still wonder about real production deployment in EC2: The whole application is running on EC2, right? What about the size of your databases? Isn't there some kind of restriction on the amount of disk memory usable by an EC2 image? I mean, if your application does some serious data juggling, ala "I want my own Ebay", where is all that data going to? Is there some "well-known" pattern for using EC2 for this kind of data-intense applications?


6. Krishna left...
Friday, 11 January 2008 3:46 am :: http://www.reffos.com/blog

Is the Java web app environment AMI is already available in EC2 or do I have to creaete one.

Is there any standard AMI packages available which I can make use of?


7. Chris Richardson left...
Friday, 11 January 2008 8:41 am

Krishna,

I've created a couple of AMIs (32-bit and 64-bit) that have Tomcat, MySql, Jmeter, Jets3t etc installed. The starting point for my AMIs were the CENTOS5 public AMIs created by www.rightscale.com. I then ran my installation script and created my AMIs. My plan is to make them publicly accessible so you won't need to create your own.

Chris


8. Alex left...
Friday, 14 March 2008 8:08 am :: http://avasseur.blogspot.com

Hey Chris, I happen to be after a similar idea but bottom up. I am currently looking for an rPath equivalent but for Java that is a *small* VM (for VMWare, for EC2, for Xen whatever) with a JVM in there already available. Period. I have tried Ubuntu 7.1 jeOS (available from VMWare forum, less than 200M) but that one is a pain to convert to EC2. I have tried rPath as well (500M) but the rBuilder Online is not really nice to work with and the rPath Linux is somewhat not something I want to familiiarize with. From what I read you have started from CentOS 5 AMI. Few questions: how big are they, how much useless stuff in there if I *just* run Java JSE ?, etc. I think this would be terrific to provide a VM with just JSE inside, in multiple hypervisor formats but with some common shared how-to for java folks (and why not later on an http appliance admin ala rPath rAPA). Drop me a note if you are after that.


9. ryanK left...
Tuesday, 1 April 2008 6:59 am

Alex, try CohesiveFT's Elastic Server On-Demand (es.cohesiveft.com) which allows on the fly provisioning of virtual machines for a number of different virtualization platforms (vmware, parallels, xen, even auto-deploy to Amazon's EC2).

The base OS for all the Elastic Servers (what they call virtual machines) is an extremely small footprint Debian-based linux. To get Java into the Elastic Server you can include a component like Tomcat or AMQP in your build or just use apt-get to load a specific version of java. Nothing new to learn!


10. cocoy left...
Friday, 4 April 2008 6:57 pm :: http://imcocoy.blogspot.com

Hi Chris,

  • Nice to see hear about this project. Do you able to have the AMI's for public so we can test ec2deploy?


11. Aaron White left...
Friday, 18 April 2008 8:38 am :: http://aaronwhite.tumblr.com

Hi Chris... nice work! Are the AMI's now publicly available?


12. Lalapet left...
Saturday, 28 June 2008 5:36 pm

Great article Chris. Thank you. I'm also right now using your Grails EC2 Plugin. I'm new to Amazon EC2 services. I have used a public AMI and got a lot of issues my grails application itself not running in Amazon EC2. Can I use the AMI that you have created? Thanks, Lalapet


13. Chris Richardson left...
Saturday, 28 June 2008 8:03 pm

Send me your numeric amazon account id (http://www.chrisrichardson.net/contactus.html) and I will give you access to the AMIs - they are all set up to work with the Maven and Grails plugins. One day soon I plan to make the AMIs public.