nginx と gunicorn と meinheld を連携させる

nginx と gunicorn + meinheld を組み合わせた時のメモ。


nginx はリバースプロキシとして gunicorn に飛ばし、gunicorn の worker として meinheld を使った。
環境は Fedora13。

nginx は yum でインストール。
/etc/nginx/conf.d/virtual.conf に以下を追加。
Green Unicorn - Deployment にあるのをほぼそのまま。

upstream app_server {
  server unix:/var/run/gunicorn/gunicorn.sock fail_timeout=0;
  # For a TCP configuration:
  #server 192.168.1.2:8000 fail_timeout=0;
}

server {
  listen 80 default;
  client_max_body_size 4G;
  server_name 192.168.1.2

  keepalive_timeout 5;

  # path for static files
  root /path/to/app/static;

  location / {
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_redirect off;

      if (!-f $request_filename) {
          proxy_pass http://app_server;
          break;
      }
  }

  error_page 500 502 503 504 /500.html;
  location = /50x.html {
    root   /usr/share/nginx/html;
  }
}

gunicorn と meinheld はそれぞれ pip からインストール。
gunicorn の設定ファイル。
gunicorn/example_config.py at master · benoitc/gunicorn · GitHub を参考に /path/to/app/conf/gunicorn.conf.py に以下を変更して設置。

import os

def numCpus():
    if not hasattr(os, 'sysconf'):
        raise RuntimeError('No sysconf detected.')
    return os.sysconf('SC_NPROCESSORS_ONLN')

bind = 'unix:/var/run/gunicorn/gunicorn.sock'
workers = numCpus() * 2 + 1
worker_class = 'egg:meinheld#gunicorn_worker'
pidfile = '/var/run/gunicorn/gunicorn.pid'

gunicorn は nginx と同一のマシンにあるので、Unix domain socket で起動する。
gunicorn は以下のようにして起動。

$ gunicorn -c config/gunicorn.conf.py run:app

これで http://192.168.1.2 にアクセスすると、アプリケーションが起動した。


開発環境は Mac のため meinheld は動かないので gevent を使っている。
あとアプリケーションに変更があったら、毎回再起動するのがめんどくさいので、以下を設定した。
http://github.com/benoitc/gunicorn/blob/master/examples/example_gevent_reloader.py


参考文献
Green Unicorn - Deployment
gunicorn/example_config.py at master · benoitc/gunicorn · GitHub
meinheld · PyPI
http://flask.pocoo.org/docs/deploying/others/#gunicorn