3

I'm trying to get a very high performing webserver setup for handling long-polling, websockets etc. I have a VM running (Rackspace) with 1GB RAM / 4 cores. I've setup a very simple gunicorn 'hello world' application with (async) gevent workers. In front of gunicorn, I put Nginx with a simple proxy to Gunicorn. Using ab, Gunicorn spits out 7700 requests/sec, where Nginx only does a 5000 request/sec. Is such a performance degradation expected?

Hello world:

#!/usr/bin/env python
def application(environ, start_response):
    start_response("200 OK", [("Content-type", "text/plain")])
    return [ "Hello World!" ]

Gunicorn:

gunicorn -w8 -k gevent --keep-alive 60 application:application

Nginx (stripped):

user www-data;
worker_processes 4;
pid /var/run/nginx.pid;

events {
    worker_connections 768;
}    
http {
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    upstream app_server {
        server 127.0.0.1:8000 fail_timeout=0;
    }    
    server {
        listen 8080 default;
        keepalive_timeout 5;
        root /home/app/app/static;
        location / {
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
            proxy_redirect off;
            proxy_pass   http://app_server;
        }
    }
}

Benchmark: (results: nginx TCP, nginx UNIX, gunicorn)

ab -c 32 -n 12000 -k http://localhost:[8000|8080]/

Running gunicorn over a unix socket gives somewhat higher throughput (5500 r/s), but it still does't match raw gunicorn's performance.

2 Answers 2

1

You can reduce the connection timeout to 0 seconds for gunicorn by using:

http://docs.gunicorn.org/en/latest/settings.html#timeout

You can also use keep_alive for the proxy_pass backend by using this directive: http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive

be aware, that the keep alive directive is not available in older nginx versions

1
  • Your gunicorn link just goes to the homepage now. Can you update it? Feb 6, 2014 at 6:55
0

Nginx does not use keepalive with backends so you should disable it in gunicorn. Also I would start testing nginx with 1 worker so that it does not compete with gunicorn for a free cpu. You may need to increase worker connections if they are not recycled fast enough.

Also, you will never achieve the same performance as raw gunicorn since nginx introduces it's own latency (albeit low). You could serve your application directly with gunicorn and static assets with nginx in another domain, this have some advantages such as cookie clean traffic.

3
  • I tried varying worker_processes and worker_connections which resulted in the same performance. Even with gunicorn with only 3 workers (1 free CPU for nginx) resulted in the same performance. I did not expect to achieve the same performance as raw gunicorn (see question title), but did not expect to see this much a difference. Of course real-world testing might result in a smaller difference compared to Hello World, as the application itself needs more time.
    – bouke
    Feb 16, 2012 at 13:37
  • However, I could not find a way to disable keepalive on gunicorn's end, can you point me some howto?
    – bouke
    Feb 16, 2012 at 13:38
  • For this particular test I would also try setting proxy_buffering and tcp_nopush off in nginx. For gunicorn Keepalive should be disabled setting it to 0 but I've found some related bugs disabling keepalive with gevent so try also 1-2 seconds if you get many errors.
    – Ochoto
    Feb 17, 2012 at 9:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .