某アプリのバックエンドをFlask+uWSGI+Nginxでつくったのでやったことまとめました。
Nginxとの連携
wsgiプロトコルで繋げる方法
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:3031;
}
socket=127.0.0.1:3031
ちなみにこの設定だと、uWSGIだけデバッグデバッグーとか言って http://127.0.0.1:3031 をブラウザで叩いても何も見えないです。uwsgiのオプションのsocket
とhttp
の違いを知らずに数分ハマった。
httpプロキシとして繋げる方法
location / {
include uwsgi_params;
proxy_pass http://127.0.0.1:3031;
}
http=127.0.0.1:3031
直感的なプロキシ。最初これしか方法ないと思ってた。これは http://127.0.0.1:3031 で見えるやつです。
socketで繋げる方法(採用)
アプリ複数公開するとき余計なポート番号消費しないので基本これでいいと思う。これ採用。
location / {
include uwsgi_params;
uwsgi_pass unix:/path/to/app/app.sock;
}
socket=/path/to/app/app.sock
uWSGI Emperor
複数アプリをuWSGIで管理するとき便利なので使う。
参考:http://qiita.com/5t111111/items/e170fead91261621b054#1-8
自動起動も楽になった!
細かいチューニングパラメタ
processes
とか limit-as
とか max-requests
とか harakiri
とか。harakiriて。
参考:http://docs.djangoproject.jp/en/latest/howto/deployment/wsgi/uwsgi.html
DjangoのサイトだけどwsgiアプリならFlaskとかでも参考になる。
ちなみにdaemonize
やmaster
はEmperorを使ってるのでONにしてない。多分そういうことだと思うけど違ったらすいません。ツッコミ待ちです。
負荷試験とかやりながら設定いじる。
デプロイ時uWSGIリロード
ファイル変更しても反映されないので、
touch-reload=/path/to/app/reload.trigger
とかにして、デプロイ時に /path/to/app/reload.trigger
をtouchしてやると、次回リクエスト受付時にuWSGIがリロードする。
デプロイのスクリプトにtouchを仕込んでおくことにした。
参考:http://field-notes.hatenablog.jp/entry/2012/05/09/115600
(別解)
ファイルを監視する。
参考:http://d.hatena.ne.jp/dayflower/20121017/1350447805
ログローテートでログファイルを見失わない
リリース後にギャーってなるやつ。
touch-logreopen=/path/to/app/logreopen.trigger
とかにして、
/path/to/uwsgi.log {
daily
rotate 7
missingok
notifempty
compress
sharedscripts
size 1M
postrotate
touch /path/to/app/logreopen.trigger
endscript
}
参考:http://taichino.com/memo/3843
(追記)結局こんな感じにしてますっての書いとくね
/etc/nginx/conf.d/sample_nginx.conf
# IPで叩かれたとき嫌だから。なくてもいい
server {
listen 80 default_server;
server_name _;
root /var/app/dummy;
index index.html;
}
server {
listen 80;
server_name sample.com;
charset utf-8;
client_max_body_size 75M;
location / { try_files $uri @uwsgi; }
# static はNginxに任せよう
location /static/ {
root /var/app/sample/webapp;
}
location @uwsgi {
include uwsgi_params;
uwsgi_pass unix:/var/app/sample/sample_uwsgi.sock;
}
}
/etc/uwsgi/vassals/sample_uwsgi.ini
uWSGI Emperorのためにuwsgi.iniを /etc/uwsgi/vassals/ にまとめとく。
[uwsgi]
base = /var/app/sample
app = main # Flask開始するのがmain.py だったら main
# Djangoの場合は sample.wsgi:application みたいな感じ
module = %(app)
# このアプリを動かすvirtualenv へのパス
# 生Pythonつかってる場合はPythonのディレクトリへのパスかな?
home = /home/www-data/venvs/sampleapp
pythonpath = %(base)
socket = %(base)/%n.sock
chmod-socket = 666
#the variable that holds a flask application inside the module imported at line #6
callable = app
# ロギング
logto = /var/log/uwsgi/%n.log
# logrotate の postrotate に仕込むやつ
touch-logreopen = %(base)/.logreopen_trigger
# uwsgi をリロードするトリガ
touch-reload = %(base)/.uwsgi_touch
max-requests = 1000
harakiri = 60
# emperorから使うからコメントアウトしてみた
#master=True
#daemonize=/var/log/uwsgi/sample.log
/etc/init/uwsgi.conf (uWSGI Emperor起動用) (CentOS6用)
description "uWSGI"
start on runlevel [2345]
stop on runlevel [06]
respawn
# uwsgi emperor 用に uwsgi だけインストールした uwsgi という名前のvirtualenv 切ってます。ぼくは。
# そうでない場合は、uwsgi のインストール先を指定すればうごく筈
env UWSGI=/home/www-data/venvs/uwsgi/bin/uwsgi
env LOGTO=/var/log/uwsgi/emperor.log
# uid と gid は適宜変える
exec $UWSGI --master --emperor /etc/uwsgi/vassals --die-on-term --uid www-data --gid www-data --logto $LOGTO
start uwsgi
で/etc/uwsgi/vassals 以下のuwsgiアプリ全部起動。
自動起動も適宜やる
/etc/systemd/system/uwsgi.service (uWSGI Emperor起動用) (CentOS7用)
[Unit]
Description=uWSGI
After=syslog.target
[Service]
# uwsgi emperor 用に uwsgi だけインストールした uwsgi という名前のvirtualenv 切ってます。ぼくは。
# そうでない場合は、uwsgi のインストール先を指定すればうごく筈
# あと uid と gid は適宜変える
ExecStart=/home/www-data/venvs/uwsgi/bin/uwsgi --master --emperor /etc/uwsgi/vassals --die-on-term --uid www-data --gid www-data --logto /var/log/uwsgi/emperor.log
Restart=always
KillSignal=SIGQUIT
Type=notify
StandardError=syslog
NotifyAccess=all
[Install]
WantedBy=multi-user.target
systemctl start uwsgi
で/etc/uwsgi/vassals 以下のuwsgiアプリ全部起動。
自動起動は適宜。