Hi all,
this may be a little off-topic but I thought I post it anyway...
In my use of Apache/mod_perl as an app. server, I needed a way to
control maximum concurrency for a given task. An example: I have a
handler that runs a task on behalf of a given customer out of a
(limited) set of customers. I don't want to hog all my Apache children
for one customer by going up to MaxClient children and deny all other
requests so all other customers are out of luck.
Something like mod_throttle isn't an option as I don't want to simply
discard requests as they come in, I still have to process them but at a
later time.
As Perrin indicated several times, the data-sharing between Apache
children is easily solved using for instance MLDBM::Sync or IPC::MM.
So I whipped up a class which uses IPC::MM to maintain a shared hash,
each key is a given id (in the above example that would be a unique
customer id) and in the value, I keep a counter.
Example code:
sub handler
{
my $request = shift;
...
my $id;
# parse request etc., sets $id based on something in the request (url
param/http header/whatever)
# get scoreboard (singleton, constructed in parent, shared by
children), this is an object that maintains the shared cache
my $scoreBoard = TTGP::Edge::Server::ScoreBoard->instance();
my ($yesCanDo, $concurrencyLevel) = $scoreBoard->canDo($id);
if ($yesCanDo) {
# process the request, currently $concurrencyLevel requests
running for this id
} else {
# Oops, we reached the maximum
# Drop request in some (persistent) queue where a daemon (or cron
job) picks it up later
}
...
# and tell $scoreBoard we're done with this $id
$scoreBoard->done($id);
}
Quite cool: I can send a stream of requests for a given id to my handler
and still have enough children available for other work.
I hope I can generalize this and send it off to CPAN.
My Apache/mod_perl-based app server went up another step in usefullness
today!
Regards,
Bas.