fastcgi-nginx vs mod_wsgi-apache
"mod_python 終了のお知らせ" を受け、もともとリソース不足だった既存の Django アプリケーション郡のサーバをリプレイスすることにしました。リプレイス要件↓
- パフォーマンスが高いのにしたい
- アプリケーションの変更は必要最小限にしたい
- URL 類は既存のアプリケーションを引継ぐ: 複数プロジェクトをサブディレクトリーで運用していて、 "django.root" で複数プロジェクトを切り分けている
環境設定について
これは apache - mod_wsgi が簡単すぎます。
nginx - fastcgi
nginx - fastcgi 構成の場合は、init.d への登録、 daemontools を利用 (弊社は mod_python 以外はこれ)。
nginx の設定
/etc/nginx/fastcgi_params
fastcgi_read_timeout 180; send_timeout 180; fastcgi_param QUERY_STRING $query_string; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param CONTENT_TYPE $content_type; fastcgi_param CONTENT_LENGTH $content_length; fastcgi_param PATH_INFO $fastcgi_script_name; fastcgi_param SERVER_PROTOCOL $server_protocol; fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; fastcgi_param REMOTE_ADDR $remote_addr; fastcgi_param REMOTE_PORT $remote_port; fastcgi_param SERVER_ADDR $server_addr; fastcgi_param SERVER_PORT $server_port; fastcgi_param SERVER_NAME $server_name; fastcgi_pass_header Authorization; fastcgi_intercept_errors off;
/etc/nginx/sites-enabled/default
server { listen 80; server_name example.com; access_log /var/log/nginx/example.com.access.log; # No www ! <- www を付けたくない場合の設定 if ($host = 'www.example.com' ) { rewrite ^/(.*)$ http://example.com/$1 permanent; } # Django の設定 <- 各 Django プロジェクトはポートで分ける location / { include /etc/nginx/fastcgi_params; fastcgi_pass 127.0.0.1:8080; } # Admin sites の設定 <- ローカルからに限定する location /admin { include /etc/nginx/fastcgi_params; fastcgi_pass 127.0.0.1:8080; allow [LOCAL_IP_ADDRESS]; deny all; } # Static Files location /static { root /path/to/staticfiles; access_log off; # アクセスログいらない } # Admin medias location /media { root /path/to/django/contrib/admin/media; access_log off; # アクセスログいらない } }
fastcgi の起動を init.d に登録
Django FastCGI init.d script for Linux を参考に、init.d スクリプトを作成し、反映する。
update-rc.d /etc/init.d/fastcgi defaults
daemontools の設定
# パッケージ名は daemontools or svtools のいずれか sudo aptitude install daemontools daemontools-run
プロジェクト毎に、デーモンツールを作成する。
/etc/service/[PROJECT]/run
#!/bin/sh # #### SERVER SPECIFIC CONFIGURATION SITE=[PROJECT] HOST=127.0.0.1 PORT=[PORT] SITES_PATH=/var/django ENVIRONMENT_PATH=$SITES_PATH/environment RUNFILES_PATH=/var/run/django RUN_AS=www-data MAXREQUESTS=1000 #### DO NOT CHANGE ANYTHING AFTER THIS LINE! # PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin DESC="[PROJECT DESCRIPTION]" cd $SITES_PATH/$SITE # find python binary to use if [ -f $ENVIRONMENT_PATH/$SITE/bin/python ]; then PYTHON=$ENVIRONMENT_PATH/$SITE/bin/python else PYTHON=`which python` fi exec 2>&1 exec setuidgid $RUN_AS \ /usr/bin/env -- $PYTHON \ $SITES_PATH/$SITE/manage.py runfcgi \ protocol=fcgi method=threaded maxrequests=$MAXREQUESTS \ host=$HOST port=$PORT \ pidfile=$RUNFILES_PATH/$SITE.pid \ daemonize=false chmod -R 777 $RUNFILES_PATH
mod_wsgi - apache
wsgi 用スクリプトの作成
各 Django アプリケーションごとに作成します。settings.py と同一階層に置くことを前提。
#!/usr/bin/python # -*- encoding: utf-8 -*- # wsgi_handler.py import sys import os # print デバッグとかしてるとこけるから、追加しちゃった。 sys.stdout = sys.stderr sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/..') os.environ['DJANGO_SETTINGS_MODULE'] = '[PROJECT].settings' import django.core.handlers.wsgi application = django.core.handlers.wsgi.WSGIHandler()
mod_wsgi の設定
sudo aptitude install libapache2-mod-wsgi
<VirtualHost *:80> ServerAdmin mail@example.com ServerName example.com DocumentRoot /var/www # Django settings WSGIScriptAlias / /path/to/project/wsgi_handler.py ErrorLog /var/log/apache2/error.log # Possible values include: debug, info, notice, warn, error, crit, # alert, emerg. LogLevel warn CustomLog /var/log/apache2/access.log combined </VirtualHost>
daemon mode で起動したい場合の設定は、id:pyxis-dev さんのサイトが参考になります。私も daemon mode で運用しています。
パフォーマンスについて
結論から言うと、fastcgi も mod_wsgi も uwsgi もパフォーマンスに大きな差はありません (mod_python よりは早い) でした。パフォーマンスの差異については、 id:perezvon さんや Alexander Solovyov さんのサイト (英語) 等も参考になります。私がテストした環境だと、初回アクセス時のみ fastcgi の方が若干早かったですが、やはりその後は誤差の範囲内です。
mod_python からの移行について (URL とか)
前述のように、複数の Django プロジェクトをサブディレクトリで運用している場合は、 mod_wsgi の方が簡単です。 mod_python でいうところの "django.root" は mod_wsgi では以下のように設定できます。
# mod_python <Location "/mysite/"> SetHandler python-program PythonHandler django.core.handlers.modpython SetEnv DJANGO_SETTINGS_MODULE mysite.settings PythonOption django.root /mysite PythonDebug On </Location> <Location "/mysite2/"> SetHandler python-program PythonHandler django.core.handlers.modpython SetEnv DJANGO_SETTINGS_MODULE mysite2.settings PythonOption django.root /mysite2 PythonDebug On </Location>
# mod_wsgi <VirtualHost *:80> WSGIScriptAlias /mysite /path/to/django/mysite/wsgi_handler.py WSGIScriptAlias /mysite2 /path/to/django/mysite2/wsgi_handler.py </VirtualHost>
fastcgi の場合は、rewrite の利用や、FORCE_SCRIPT_NAME で置き換えるか、 urls.py を書き換える必要があります。めんどい・・・。
ということで mod_wsgi を使うことにしましたよ!
コメント
コメントを投稿