A quick introduction to Perlbal

Tagged:  

If you're hoping to one day reach the point where your web application is growing to hundreds or thousands of hits per second then you need to be ready to scale out. One part of this involves being able to balance the load across a few backend servers, or just splitting your requests between static content (images, css, javascript) and application content. Enter Perlbal.

Perlbal is one of the interesting tools from the makers of memcached and mogilefs, Danga. A while their tools may be cool, they're a little sparsely documented. So here is a start.

To install, you'll first want to have the follow packages installed for debian/ubuntu:
perl perl-base perl-modules libwww-perl libcompress-zlib-perl libsys-syscall-perl libbsd-resource-perl libio-aio-perl libdanga-socket-perl

Then download Perlbal from the site, perl Makefile.PL, make, make test and make install.

The configuration file for perlbal sits in /etc/perlbal/perlbal.conf. The config consists of groups of commands which can also be passed directly to the running server via the management interface. These commands consist of five main types:
* controlling the load balancer from the management interface, e.g. shutdown, lod/unload plugins, etc
* getting info about the load balancer from the management interface
* configuring server pools
* configuring the services available
* setting parameters for the load balancer

There a four types of services which can be configured on Perlbal:
* 'reverse_proxy' for a service that load balances to a pool of backend webserver nodes
* 'web_server' for a typical webserver
* 'management' for a Perlbal management interface (speaks both command-line or HTTP, auto-detected)
* 'selector', for a virtual service that maps onto other services

As a little example, I set up a proxy interface to load balance between two instances of a rails application. So, first thing first, I started up two instances of my rails app, running on different ports:

railsapp$ ./script/server -p 5000
railsapp$ ./script/server -p 6000

I then set up Perlbal to load balance between these, so here is the contents of the perlbal.conf:

CREATE SERVICE mgmt
SET role = management
SET listen = 127.0.0.1:8065
ENABLE mgmt

CREATE POOL web_proxy_pool
POOL web_proxy_pool ADD 127.0.0.1:5000
POOL web_proxy_pool ADD 127.0.0.1:6000

CREATE SERVICE web_proxy
SET listen = 127.0.0.1:4000
SET role = reverse_proxy
SET pool = web_proxy_pool
SET persist_backend = on
SET max_backend_uses = 10
SET backend_persist_cache = 2
SET verify_backend = on
SET balance_method = random
SET enable_reproxy = on
SET buffer_uploads = off
ENABLE web_proxy

What this does is it first sets up a management interface listening on port 8065. Once we start up perlbal, we can telnet to that interface and check that everything is running. What it does next is create a pool of our two rails servers. It then creates load balanced interface listening on port 4000. All of the options for the service are defined in doc/service-parameters.txt in the Perlbal code. At the moment there seems to only be a choice between round robin and random balance methods.

So now we fire up Perlbal and try it. Run perlbal -d and try going to localhost:4000 in your browser. You should see your rails app. Running it a few times, you should switch between the two instances. Try shutting down one of the rails instances and you should see it fail-over to the running instance only.

To have a quick look at the management interface run telnet localhost 8065. Then try the following commands:

show pool
show pool web_proxy_pool
show service
show service web_proxy

That's all for the moment. I might try to put together some docs on setting up redirecting based on URLs later.