Nelson's log

nginx proxy buffering

It took a lot of head scratching, but I think I figured out nginx and how to configure buffering of proxies. Long story short, here’s where I ended up:


location /rivers {
  proxy_pass http://localhost:8000;
  proxy_buffering on;
  proxy_buffers 32 16k;
}

If I did that right, it means “proxy to this other HTTP server and buffer 512kb of data from it”. The default configuration is to buffer only 32k, which in the modern world seems awfully small. But nginx allocates this memory per request, so if I were expecting a lot of requests that would be a bad idea. nginx will also buffer to disk if it runs out of memory buffer, up to 1G or so, but I wanted to avoid that. Note that nginx is buffering uncompressed data.

With this setup I can have 9 clients slowly loading the big tile 4/3/6.json even though I only have four Gunicorn workers. And I verified via sudo inotifywait -m -r /var/lib/nginx/ that it wasn’t using the file cache. Good enough for me.

Here’s a quicky slow client I used to test the buffering:


#!/usr/bin/env python

import socket, time, sys

req = [
'GET /rivers/4/3/6.json HTTP/1.1',
'Host: www.somebits.com',
'Accept-Encoding: gzip',
'Connection: close',
'', '']
readSize = 1600

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('somebits.com', 8001))
s.sendall('\r\n'.join(req))
l = 0
while True:
    time.sleep(1)
    d = s.recv(readSize)
    l += len(d)
    if len(d) == 0:
        break
    sys.stdout.write("%s" % "*" if len(d) == readSize else ".")

s.close()
print '\nReceived', l, "bytes"