Tuesday, July 5, 2011

Tomcat clustering on Amazon

This blog post is actually from a coworker of mine, Jason Bennett. For our work, we had to get Tomcat clustering running on Amazon and had a real time of it. So, for the benefit of others, he posted his experience (Thank Jason!)

Tomcat session replication on Amazon Web Services (AWS) is not much different from replication in any machine cluster, with the major exception that Amazon does not allow multicast traffic, the usual basis of Tomcat replication. Tomcat does, however, support static replication, which works just fine in Amazon’s cloud.

Initially, read the Tomcat session replication documentation and follow the basic configuration (under For The Impatient). Note that the FarmWarDeployer is not necessary if you don’t care about deploying once across the cluster. Make sure to set the NioReceiver port if needed, and ensure that this port is allowed under your security configuration. This last point is very important! Most of the problems you will encounter in setting up replication are Amazon configuration problems, not Tomcat problems. If you are running two Tomcats on the same box (for some reason), these ports must be different on the two instances.

Next, review the Cluster Basics in the documentation and ensure that you have followed ALL of them. Double check your time settings, make sure your two tomcats are accessed via a single URL, and that your web.xml file is marked properly.

Finally, we need to configure the static cluster. Refer to the documentation and paste the example within the tag. Make the port attribute match the value in your NioReceiver, the host attribute match another machine in your cluster, and the uniqueId field be different from any other static entry in this file. Add an additional entry for each member of your cluster. More than likely, you will paste the template and change only the host and uniqueId values.

At this point, start up your servers. You should see an entry like this:

org.apache.catalina.ha.tcp.SimpleTcpCluster memberAdded
INFO: Replication member added:org.apache.catalina.tribes.membership.MemberImpl[tcp://10.10.40.101:4000,10.10.40.101,4000, alive=0, securePort=-1, UDP Port=-1, id={0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 }, payload={}, command={}, domain={115 98 45 98 117 105 108 100 101 ...(15)}, ]

Your first server should have an entry that says “no other members found” while your remaining servers will connect with a string like the above.

Possible reasons for failure:
1. Make sure that you’ve allowed the required ports in the Amazon config. This is your most likely source of problems, especially if you got it to work outside of the Amazon.
2. Double-check your configuration. Make sure that the ports are not being used elsewhere, and that your static configuration port matches your NioReceiver port on the OTHER machine.
3. Make sure you’re accessing both machines via the same URL. If you use different URLs, the sessions will be different.

If you still cannot get the replication to work, try setting up two Tomcat instances on a single machine. Getting that setup to work should prove the concept, meaning any issues across machines are network problems or configuration typos.

Good luck, and remember that it can work!

Wednesday, March 23, 2011

The coolest thing since sliced cheese...

I've been put in charge of a new project - we're building an application that is a bit secret - so I can't get into details. But - it's effectively an app that let's you build documents. Naturally, I was looking for a backend architecture that was document-oriented - not relational. I initially thought to make it xml based and use XSLT or an equivalent xpath based transform technology.

Then we started looking into MongoDB. It really fit the bill; however, it was JSON based. So what to do - I want to avoid an ORM or anything that requires a lot of data binding defintions - I want the app to be loose, lightweight and incredibly agile. JSON is all of that - but how do I validate? XML has XSD but what do I do for JSON? Also, I want to efficiently query documents - XPATH is a very efficient way to query. How do I achieve the equivalent with MongoDB?

Well I then discovered Spring DATA. Wow! Where have you been all my life!?! What does Spring Data do? Well, it provides access services to noSQL DBs. But the magic isn't that it's simply a DAO but it's the way it implemented these services. I wish Hibernate or MyBatis worked the same way. Basically all you have to do is define your Pojos, create a repository interface by descending from the MongoRepository interface, set the host name and port of your MongoDB and that's it!! Spring implements all CRUD automagically from the interface. Additionally if you add "find" methods on the interface, Spring automagically generates queries. No mapping files, no schema, no mastering of various query language - heck, you don't even have to annotate your code! Seriously, this one of the most useful and productive bit of technology that I ever used.

So there you have it - I have a data model/persistence layer that is easy to create and modify. It is just the right balance of strong typing without the headache that comes with a formal persistence mechanism.

To the Spring Data Team : awesome job!!! You guys are rock stars!!

Wednesday, January 19, 2011

Two days down the drain...

I just wasted two days trying to restore my eclipse environment.

Late Friday afternoon, out of the blue, the eclipse IDE on my Mac OSX laptop no longer was able to run the debugger. I kept receiving the follow error:

Invalid memory access of location 0x14 rip=0x1007f6d22

After much fruitless searching and dead end attempts to fix it, I decided to reinstall the OS. No luck, still broken - but after a second install, I got a different error message that pointed to the problem: During the updating of my hosts file, I had accidentally blown away my localhost definition. After I restored the defintion, voila - problem solved!