Nginx + uWSGI 導入メモ

nginxインストール・動作確認
nginx を aws EC2 にインストールする
http://d.hatena.ne.jp/january/20130819/1376866225

$ sudo yum install nginx

pipインストール

$ sudo yum install python-setuptools
$ sudo easy_install pip

uwsgiインストール・動作確認
NginxとPython
http://d.hatena.ne.jp/maemaewater/20130701/1372691110

$ sudo yum install make gcc
$ sudo yum install python-devel
$ sudo yum install pcre pcre-devel
$ sudo pip install uwsgi
    :
    ################# uWSGI configuration #################

    pcre = True
    kernel = Linux
    malloc = libc
    execinfo = False
    ifaddrs = True
    ssl = False
    zlib = False
    locking = pthread_mutex
    plugin_dir = .
    timer = timerfd
    yaml = embedded
    json = False
    filemonitor = inotify
    routing = True
    debug = False
    capabilities = False
    xml = False
    event = epoll

    ############## end of uWSGI configuration #############
    total build time: 20 seconds
    *** uWSGI is ready, launch it with /usr/bin/uwsgi ***
Successfully installed uwsgi
Cleaning up...

uwsgi設定ファイルをつくる

$ sudo vim /home/uwsgi/config.yaml
uwsgi:
  socket: /home/uwsgi/socket
  touch-reload: /home/uwsgi/touch.reload
  touch-logreopen: /home/uwsgi/touch.logreopen
  daemonize: /home/uwsgi/log/uwsgi.log
#  pythonpath: /home/www/root/wsgi/
#  module: wsgihandler
  wsgi-file: /home/www/root/wsgi/wsgihandler.py
  uid: nginx
  gid: nginx
  processes: 2
  threads: 3
  master: true

/home/www/root/wsgi/wsgihandler.py

def application(environ, start_response):
        start_response('200 OK', [('Content-type', 'text/plain')])
        return 'Hello World!'

uwsgi設定ファイルで起動確認

$ sudo touch /home/uwsgi/touch.reload
$ sudo touch /home/uwsgi/touch.logreopen
$ sudo mkdir /home/uwsgi/log
$ sudo chown -R nginx:nginx /home/uwsgi
$ sudo uwsgi --yaml /home/uwsgi/config.yaml

uwsgiサービス起動停止スクリプトをつくる

$ sudo vim /etc/init.d/uwsgi
#!/bin/bash
#
# uwsgi - this script starts and stops the uwsgi daemon
#
# chkconfig:   - 84 16
# description: uwsgi is a WSGI server.
# processname: uwsgi

# Source function library.
. /etc/init.d/functions

path="/usr/bin/uwsgi"
name=$(basename $path)
config="/home/${name}/config.yaml"
pidfile="/var/run/${name}.pid"
lockfile="/var/lock/subsys/$name"
RETVAL=0

start() {
    echo -n $"Starting $name: "

    daemon ${path} --yaml ${config} --pidfile ${pidfile}
    RETVAL=$?
    echo
    [ $RETVAL = 0 ] && touch ${lockfile}
    return $RETVAL
}

stop() {
    echo -n $"Stopping $name: "
    killproc -p ${pidfile} ${name} -INT
    RETVAL=$?
    echo
    [ $RETVAL = 0 ] && rm -f ${lockfile} ${pidfile}
}

case "$1" in
  start)
     start
     ;;
  stop)
     stop
     ;;
  status)
     status -p ${pidfile} ${path}
     RETVAL=$?
     ;;
  restart)
     stop
     start
     ;;
  *)
     echo $"Usage: $name {start|stop|restart|status}"
     RETVAL=2
esac

exit $RETVAL

OS起動時にuwsgi起動

$ sudo chkconfig --add uwsgi
$ sudo chkconfig uwsgi on
$ chkconfig
    :
uwsgi           0:off   1:off   2:on    3:on    4:on    5:on    6:off

uwsgiログローテート

$ sudo vim /etc/logrotate.d/uwsgi
/home/uwsgi/log/* {
    create 0644 nginx nginx
    daily
    rotate 10
    missingok
    notifempty
    compress
    sharedscripts
    postrotate
        touch /home/uwsgi/touch.logreopen
    endscript
}

nginxをuwsgiの前段で動くよう設定。
リクエストパス /uwsgi/ 配下ぜんぶ uwsgi に流す。

$ sudo vim /etc/nginx/nginx.conf
    :
    server {
        listen       80;
        server_name  localhost;
        root         /home/www/root;
        :
        location ~ ^/wsgi/(.*)$ {
            include uwsgi_params;
            uwsgi_pass unix:/home/uwsgi/socket;
            uwsgi_param SCRIPT_NAME /wsgi;
            uwsgi_param PATH_INFO /$1;
        }
    :

ブラウザ動作確認
http://localhostまたはDNS名/wsgi で wsgihandler.py が動く。パス /wsgi/xxx などでも同じ。

動かない時。
nginxエラーログ

$ sudo tail /var/log/nginx/error.log

uwsgiログ(wsgihandler.py で標準出力するとこのログに出る)

$ sudo tail /home/uwsgi/log/uwsgi.log

Python文法チェック

$ python -m wsgihandler.py
$ rm wsgihandler.pyc

wsgihandler.py(WSGIアプリケーション)では、リクエストパスに応じた処理を行ってレスポンスを返す。環境変数 PATH_INFO などにリクエストパスが入っており、たとえばリクエスト /wsgi/xxx の時は environ[‘PATH_INFO’] に ‘/xxx’ が入っている。たとえば以下のように処理を分岐させる。

#!/usr/bin/env python
# coding:utf-8

def top(environ, start_response):
        start_response('200 OK', [('Content-type', 'text/plain')])
        return 'I am top page'

def hello(environ, start_response):
        start_response('200 OK', [('Content-type', 'text/plain')])
        return 'Hello World!'

def NotFound(environ, start_response):
        start_response('404 Not Found', [('Content-Type','text/plain')])
        return environ.get('PATH_INFO') + ' not found'

def application(environ, start_response):
        routes = {
                '/': top,
                '/hello': hello,
        }
        return routes.get(environ.get('PATH_INFO'), NotFound)(environ, start_response)

wsgihandler.py を更新したら、uwsgi に更新を知らせる。

$ sudo touch /home/uwsgi/touch.reload

その他。
NumPyインストール

$ sudo pip install numpy
    :
Successfully installed numpy
Cleaning up...