Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

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.

share|improve this question

2 Answers 2

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

share|improve this answer
    
Your gunicorn link just goes to the homepage now. Can you update it? –  Nick Retallack Feb 6 at 6:55

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.

share|improve this answer
    
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 '12 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 '12 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 '12 at 9:57

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.