ちゃんと運用するときのuWSGI設定メモ


某アプリのバックエンドをFlask+uWSGI+Nginxでつくったのでやったことまとめました。



## Nginxとの連携

### wsgiプロトコルで繋げる方法

```nginx.conf
location / {
    include uwsgi_params;
    uwsgi_pass 127.0.0.1:3031;
}
```


```uwsgi.ini
socket=127.0.0.1:3031
```
ちなみにこの設定だと、uWSGIだけデバッグデバッグーとか言って http://127.0.0.1:3031 をブラウザで叩いても何も見えないです。uwsgiのオプションの`socket`と`http`の違いを知らずに数分ハマった。

### httpプロキシとして繋げる方法

```nginx.conf
location / {
    include uwsgi_params;
    proxy_pass http://127.0.0.1:3031;
}
```


```uwsgi.ini
http=127.0.0.1:3031
```
直感的なプロキシ。最初これしか方法ないと思ってた。これは http://127.0.0.1:3031 で見えるやつです。

### socketで繋げる方法（採用）
アプリ複数公開するとき余計なポート番号消費しないので基本これでいいと思う。これ採用。

```nginx.conf
location / {
    include uwsgi_params;
    uwsgi_pass unix:/path/to/app/app.sock;
}
```


```uwsgi.ini
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リロード
ファイル変更しても反映されないので、

```uwsgi.ini
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





## ログローテートでログファイルを見失わない

リリース後にギャーってなるやつ。

```uwsgi.ini
touch-logreopen=/path/to/app/logreopen.trigger
```
とかにして、

```logrotate設定
/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
```nginx: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/ にまとめとく。

```sample_uwsgi.ini
[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用)

```uwsgi.conf
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用)

```ini:uwsgi.service
[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アプリ全部起動。
自動起動は適宜。