Hi,
I've been meaning to write an article about how I used Apache/mod_perl
to implement a mobile SMS application platform as it demonstrates use of
Apache/mod_perl outside the Web realm, something I hadn't seen so far.
Time constraints (as always) have prevented me from doing this properly,
however, I'll try to give a short description of the system.
The goal kinda is to see if others are using Apache/mod_perl in a
similar way to share experiences, discuss issues that arise or discuss
alternatives (I'd love someone to tell me I'm an idiot for handling all
this lowlevel stuff myself and move to J2EE/java at once, if he can
convince me I could have implemented this with the same budget and time
frame).
Introduction
*************
The purpose of the application is to provide a server platform on top of
which arbitrary SMS applications can be developed quickly and provide a
stable and scalable architecture that allows for future enhancements
such as integrated billing and reporting options.
An SMS application can be characterized by subscribers sending
text-based commands to the platform, have the platform dispatch to the
right application instance. The application instance handles the
command, executing whatever application-logic defined for the particular
application, and usually generate responses to the subscriber command.
It should also be possible that the platform initiates messages to
subscribers as a result of a command from another subscriber as well as
be able to generate messages based on timers
Connecting the platform to external entities for the transmission and
reception of SMS messages such as SMSC's (SMS center; these things
distribute SMS messages directly to and from mobile subscribers) and SMS
Gateways (really a "smart" front-end to one or more SMSC's, unifying the
way to reach subscribers from multiple telco's) should be flexible
enough to be able to "plug-in" different protocols such as
HTTP/SMTP/CIMD/SMPP as needed.
All persistent data needed by SMS applications must be stored in the
underlying RDBMS. The server platform must provide access to the
persistent storage to the SMS applications.
Component architecture
**************************
Early on in the project I decided to go for a distributed component
architecture such that individual components can be deployed over
various physical machines. This will offer the required scalability as
well as allow for a convenient security scheme by allowing components to
run on segments of a network with differing outside visibility.
As I started modelling this "world", I ended up with the following
components:
1. game application server
Within this application server, multiple instances of multiple SMS
application classes should be running. This component provides two
external services:
- handleMessage(CommandRequest)
This service takes an instance of a CommandRequest object and runs the
command in the appropriate application instance.
- handleTimer(Timer)
This services handles expiry of a timer set by the application logic.
2. timer service
A persistent service that maintains timers set by application instances
within the game application server and invokes the handleTimer service
of the game application services upon expiry of a timer.
External service offered:
- setTimer(Timer)
3. virtual SMS gateway
This component is handles communication with the outside world (the
external entities such as SMSC's and SMS gateways). This component is
split up in 2 subcomponents, one that handles input from mobile
subscribers and one that handles output to mobile subscribers. Each
subcomponent provides one service:
- handleMessage(Message)
The input component receives requests from the outside world using
pluggable subcomponents that handle protocol details, the output
component transmits requests to the outside world using pluggable
subcomponents that handle protocol details.
Apache/mod_perl component containers
********************************************
When thinking about how to implement all this I was tempted to look into
doing it with some J2EE-thingy. However, there was this time-constraint
as well as a constraint on available programmer-hands (I tricked
management into hiring one programmer for 20 days, the rest I had to do
by myself). Then it struck me that this game application server really
looked like a vanilla regular mod_perl web application: receive request
from user, process, send back reply. No html though, but Message objects
that could be serialized/deserialized from text strings. There were of
course some differences: the reply is not sent back inline (i.e. upon
reception of a request via SMS, you can't "reply"; you have to create a
whole new message and send that to the originator of the message) and
there was this timer service: I can't make Apache/mod_perl do work
without having it received a user-initiated request.
The good thing was I've been doing Apache/mod_perl for some years so I
knew beforehand I could create a schedule acceptable from the business
point of view that was also feasible based on experience with the
technology.
So, for each component except the timer service, I created physical
Apache/mod_perl instances, one for the game application server, one for
the SMS output component and one for the SMS input component.
Each instance really only defines one or two URL's that access the
service provided by the component running in the instance.
Component communication
******************************
I took a shortcut here. I really wanted to go for SOAP here as it's a
natural fit and it will allow me to move components to other languages
(management and marketing still seems hung up on java) fairly easy. My
personal experiences with SOAP on earlier projects weren't too good and
I just couldn't fit playing with SOAP into my schedule. So I took my old
friends LWP::UserAgent, HTTP::Request and Storable to handle this part
(perl object instance -> Storable freeze -> HTTP post -> Storable
thaw -> perl object instance).
The good thing is that this is a minor part of the whole system and I
know I can put SOAP in easily when the need arises.
Result
*******
We had the platform in place in about 6 weeks, starting with absolutely
nothing: no hardware, no development environment, no technology choices
made beforehand. Also based on former experience, the decision to go
with a LAMP architecture (Linux, Apache, MySQL, Perl) running on fairly
cheap intel boxen was made quickly. MySQL was, and is, not on my
wishlist, but the whole battle of moving Oracle in would be both a time
and money killer, either of which we didn't have a lot of at the time.
Aside from having one production SMS application (a mobile SMS game),
I've done a prototype SMS application on this platform to check if it
really is easy to create new apps. It took me about 4 hours to implement
a "SMS unix commandline" application: I can login to the application
server using SMS, send Unix commands with my mobile phone and receive
their output (better make sure your command doesn't generate more than
160 characters though), the application maintains my working directory
etc..
Performance is 'good enough' with the platform running on 2 cheap Intel
boxen, it handles 40 to 60 incoming commands per second. As I haven't
spent one second on optimization yet (anyone know the command to create
an index in MySQL? :)), that number is fine for me.
Future enhancements and considerations
*********************************************
I really want SOAP. It just seems to make sense to do so as I expect the
number of components to grow as well as some non-perl components.
To handle a large number of concurrent transactions in a
transaction-safe environment without me having to worry too much about
concurrency issues and referential integrity I will slowly move to
Oracle. $dbh->do('LOCK TABLE USER, INSTANCE, APP_DATA') just plain sucks
unless you want to create a very large distributed *single-user* system
running on multiple machines.
I want a discrete layer between Apache/mod_perl and the game application
server so that I really get a generic application server with multiple
application instances providing services. running . I'd also like a
better way of describing the services that each application provides.
Some things in the current system are not abstract enough for my taste;
some parts of the code still look too much like a web server and I don't
do no stinkin' web stuff ;)
I'm still unsure about LAMP. Can we move to very cheap hardware and a
free OS when we were used to expensive HP, Sun or IBM stuff that was
*expensive* and get away with it? Personal experience and what I've read
seem to indicate we can. Live experience will tell, and if it breaks,
moving the platform to either of the above three should be a no-brainer.
We live in interesting times.
Well, that's it. Fairly longish story and yet there's a lot more to tell.
Maybe this has been interesting for some, maybe some people on this list
did similar things, I'd love to get feedback,
Best regards,
Bas Schulte.