Please take a look at those slides. They’ll give you the gist of Mongrel2’s design and I’ll elaborate on them below. Notice that the slides start by speaking about Mongrel, which is Mongrel2’s predecessor. It is fundamentally different from Mongrel2, but it does share some things, like the HTTP parser, in common.
These slides are by Paolo Negri.
Some thoughts on Mongrel2
I am somewhat enamored by Mongrel2 lately. It’s design is simple and focused, yet the server does everything you need.
Mongrel2 is the web server. So your browser, a phone or any app might go to yoursite.com and communicate with a Mongrel2 instance. Mongrel2, however, might communicate with something else to fulfill the request. By nature of using a message passing system, it becomes asynchronous and decoupled from how the work is actually being done. Something big sites all scale into eventually anyway.
By using the ZeroMQ framework for it’s message passing it also gains language independence. I could have a Python process sharing load with a Java process alongside some Lua. Any language that supports ZeroMQ can work. Mongrel2 just does web serving and leaves the rest up to you, via configuration.
ZeroMQ currently supports many lanugages
It gets better too. ZeroMQ is an extensive framework all in itself. You can open a connection to a computer that doesn’t exist and start sending messages. It will queue them up and wait for when that system comes online. You could have it simply error if you think that’s appropriate.
One of my favorite things to do is turn on Mongrel2, request a URL from my browser, then turn on one of my Python request handlers. After it’s initialized, it reads the message and responds. Mongrel2 sends the response to my browser. ZeroMQ absorbed the down handler until it was ready.
It gets a little better, still. So now I’ll open a second request handler, to pretend I’m scaling up to handle load. Mongrel2, with no config change or restart, immediately starts sending messages round-robin to each handler instance!
Request handling
Mongrel2 is configured by mapping three types of request methods: Dir, Proxy, Handler. You configure URL routes to each of these, depending on your needs. The configuration looks like below.
# here's a sample directory
media_directory = Dir(base='media/',
index_file='index.html',
default_ctype='text/plain')
# a sample proxy route
tornado_proxy = Proxy(addr='127.0.0.1', port=8000)
# a sample zeromq handler
chat_demo = Handler(send_spec='ipc://127.0.0.1:9999',
send_ident='54c6755b-9628-40a4-9a2d-cc82a816345e',
recv_spec='ipc://127.0.0.1:9998', recv_ident='')
Three types of request
If it’s a static file request M2 uses Dir handling. It reads the path and expects to find a static file there or follows some common web handling conventions, such as loading index.html. Useful for hosting media.
Proxy handling is similar to the upstream concept from Nginx. You can simply pass the request and it’s details up to something else, like Tornado or Django, for handling the request.
The Handler type is where Mongrel2 really shows it’s power. This type sends the request down a socket for handling and waits to receive responses on another socket. Communication can happen in both directions using different semantics. The handler can exist basically anywhere. It might consume a local socket, like you see configured above with the ipc socket, or it might use a tcp socket to connect to a remote system. It’s configurable and flexible.
Existing handlers
There have been a few interesting ideas for how to handle Mongrel2 sockets. You can build a handler using whatever language inspires you.
Zed wrote a framework in Lua called Tir.
For PHP there is Photon or m2php.
Some folks have written a WSGI interface to Mongrel2 messages. This lets a user run a Django instance and turn on another Django instance, to scale up, without ever bouncing the web server.
As you might know, I built MongrEvent as an example of one way to build a handler in Python. I’ve got a more robust one on the way, modeled loosely after Tornado and Bottle.
This project is Brubeck. I’ve used that name for projects in the past, but this project feels most deserving.
Digression: I’ll have to find a way to revive the Dillinger name at some point too… It’s being wasted on my experiment merging Tornado and ZeroMQ from before I got into Mongrel2.