Foundations of Python Network Programming

(WallPaper) #1

Chapter 10 ■ http ServerS


174


The choice between these four architectures has historically been driven by three features of the C Python
runtime: the interpreter is large, it is slow, and its Global Interpret Lock prevents more than one thread at a time from
executing Python bytecode.
The limitations of the interpreter lock encouraged the use of separate Python processes instead of multiple
Python threads sharing the same process. But the size of the interpreter pushed back in the other direction: only a
certain number of Python instances will easily fit into RAM, limiting the number of processes.


Running Python Under Apache

You can best appreciate the problems described earlier if you imagine an early Python-powered web site operating
under Apache with the old mod_python. Most requests to a typical web site (see Chapter 11) are for static resources: for
every request that asks Python to generate a page dynamically, there might be a dozen requests for the accompanying
CSS, JavaScript, and images. Yet mod_python burdened every Apache worker with its own copy of the Python
interpreter runtime, most of which sat idle. Only one out of every dozen workers might be running Python at a given
moment while the rest spooled out files using Apache’s core C code.
This impasse is broken if Python interpreters live in separate processes from the web server workers that shovel
static content from disk out onto waiting sockets. This spawned two competing approaches.
The first way to avoid burdening each Apache thread with a Python interpreter is to use the modern mod_wsgi
module with its “daemon process” feature activated. In this mode, Apache workers—whether threads or
processes—are spared the expense of loading or executing Python, incurring only the cost of dynamically linking to
mod_wsgi itself. Instead, mod_wsgi creates and manages a separate pool of Python worker processes to which it can
forward requests and where the WSGI application will actually be invoked. Dozens of tiny Apache workers can be
busily chattering out static files for each big Python interpreter that sits slowly building a dynamic page.


The Rise of Pure-Python HTTP Servers

However, once you have resigned yourself to the fact that Python will not live within the main server process itself
but that HTTP requests will have to be serialized and forwarded from an Apache process and into a Python process,
why not simply use HTTP? Why not configure Apache to reverse-proxy each dynamic request to Gunicorn, with your
service running inside?
True, you will now have to start and manage two different daemons—Apache and Gunicorn—where before you
only had to start Apache and let mod_wsgi take care of spawning your Python interpreters. But in return you gain a
great deal of flexibility. To begin with, there is no longer any reason that Apache and Gunicorn need to live on the
same box; you can run Apache on a server optimized for a huge number of simultaneous connections and sprawling
filesystem access and run Gunicorn on a separate server optimized for a dynamic language runtime making back-end
requests to a database.
Once Apache has been reduced from your application container to a mere static file server with reverse-proxy
capabilities, you have the option of replacing it. After all, nginx can also serve files while reverse-proxying other paths
just as well, as can many other modern web servers.
The mod_wsgi option, in the end, works out to a limited and proprietary version of real reverse proxying: you
are speaking its own internal protocol between processes that have to live on the same machine, when you could be
speaking real HTTP and have the option of running Python either on the same machine or on a different one as your
needs evolve.


The Benefits of Reverse Proxies

What about HTTP applications that serve only dynamic content, generated by Python code, and involve no static
resources? Apache or nginx might seem to have little work to do in such cases, and you might be tempted to ignore
them and expose Gunicorn or another pure Python web server directly to the world.

Free download pdf