Perlbal for chat polling

Chris Hondl chris at imvu.com
Tue Mar 21 05:08:43 UTC 2006


We've been using Perlbal at IMVU since January of this year.  IMVU is a
community service built around a 3D avatar chat client.  We've been made
some extensions to Perlbal that others might find useful.

Our chat protocol is XML over HTTP with the client polling for messages.  We
store the message queues for all the chats in memcached (the data is
inherently ephemeral and the protocol can recover if messages get dropped
due to a restart).  About a week ago we switched to an implementation where
Perlbal handles the polling requests internally using a plugin.  Our plugin
recognizes inbound polling requests, makes the calls to memcached to
determine if there are any messages for the client, and if there are
messages sends the response.   If there are no messages, the plugin puts the
request into a buffer and retries again one second later.

We've been very happy with Perlbal.  The new code is much more efficient
because there is no HTTP traffic to the client unless there are messages
that need to go out, because Perlbal can keep many more connections alive
than Apache, and because Perlbal can share state across connections.  Since
Perlbal was written in Perl (as opposed to C) and has a plugin architecture
I was able to write and ship this extension in under a week.

I made one change to the Perlbal 1.41 distribution to add a hook after the
POST data has been received from the client.  I've appended the patch to the
end of the email if anyone is interested.

There is a comment in the source for Danga socket that seemed inaccurate.
The Danga socket source says:

    # watch for writability.  not needed with ->write().  write()
    # will automatically turn on watch_write when you wrote too much
    # and turn it off when done
    $my_sock->watch_write($bool);

The behavior I observed was that Danga::Socket never actually called
watch_write(0) to turn off polling for writes and that CPU usage went to
100%.  My work around was to copy the code used elsewhere in Perlbal to turn
off write notifications by passing a coderef to a subroutine as the last
thing to write.

I also was tripped up by the management code in Perlbal.pm that assumes all
instances of Danga::Socket are also instances of Perlbal::Socket.   I
created an asynchronous memcached client that initially inherited from
Danga::Socket, but was forced to inherit from Perlbal::Socket to avoid
failures in the management code.

In addition to chat, the approach we used here might be interesting on any
site using AJAX techniques to keep data on web pages up to date.  Although
our plugin is pretty specific to our situation, we would be glad to share
with anyone interested.  I've got a few more things I want to do to the
asynchronous memcached client, but I expect to post that to the memcached
mailing list in a week or so.

Chris

--
http://avatars.imvu.com/chris




Index: C:/imvu/operations/software/Perlbal- 1.41/lib/Perlbal/ClientProxy.pm
===================================================================
--- C:/imvu/operations/software/Perlbal-1.41/lib/Perlbal/ClientProxy.pm
(revision 8072)
+++ C:/imvu/operations/software/Perlbal- 1.41/lib/Perlbal/ClientProxy.pm
(revision 8150)
@@ -684,6 +684,10 @@
     # over the buffer-to-memory size, see if we should start spooling to
disk.
     return if $self->{service}->{buffer_uploads} &&
$self->decide_to_buffer_to_disk;

+    # give plugins a chance to act on the request before we request a
backend
+    my $svc = $self->{service};
+    return if $svc->run_hook('proxy_read_request', $self);
+
     # if we fall through to here, we need to ensure that a backend is on
the
     # way, because no specialized handling took over above
     print "  finally requesting a backend\n" if Perlbal::DEBUG >= 3;
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.danga.com/pipermail/perlbal/attachments/20060320/8d4a1ccb/attachment.htm


More information about the perlbal mailing list