Hi, I’m Scott Miller, Chief Architect at Thoof. For the geeks out there, I wanted to write a short post about some of the software level decisions we made while developing Thoof. We think this stuff is interesting, so why not share it?
When we set out to design Thoof’s software architecture, we wanted to create a flexible platform for the website. Not just for delivering pages, but for implementing complex functionality quickly and easily, and with performance in mind.
Using the open source Wicket web frame work got us a lot of the way there. It allowed us to modularize components of the site, and gets a lot of the basic plumbing of logic and presentation out of the way. Next, we needed a way to keep the site fast and responsive, independent of some of the more complex processing that underlies Thoof. To do this, we added an asynchronous events system.
The events system gives us two major things. First, the ability to decouple action from reaction. This allows each component of the site to be concerned only with its inputs (dependencies) and its outputs, and keep other components blissfully ignorant of who needs its results or who is providing its inputs. In short, it cuts down on spaghetti code.
Second, events allow us to decouple the need for processing from the processing itself. Much of what goes on in a typical request to Thoof matters a great deal, but not to the request that’s occurring Right Now. By firing an event which is processed by a threaded background engine, we can race on through what actually needs to be done during the request. Even better, it means that if something is slowing down the system, its not slowing down page generation, just other background tasks.
Controlling the performance of our complex database tasks led to another decision, to use the iBatis SQL abstraction layer. Unlike typical ORM frameworks like Hibernate, or even more “hands off” systems like those employed by Rails, iBatis lets us write the SQL queries. This is more work on the front end, but gives us much greater flexibility in the long run. If a query is performing slowly, we can edit the SQL ourselves, trying different ways of ‘phrasing’ the SQL to govern performance, without affecting the DAO pattern based model objects in the application itself. It also lets us take heavy advantage of PostgreSQL views and stored procedures, so that we can not only tweak SQL, we can often do it in the database instantaneously, without having to redeploy the application.
How well does it work? We’d be remiss if we didn’t benchmark it. Under our worst case, a series of page views which we know stress both the web application logic and the database, we were able to push about 50 requests/sec from each web node. Even better, that value didn’t seem to change as concurrency varied during the test from 20 to 200 concurrent requests.