Flask 서비스를 위한 uWSGI + Nginx 설정

필요 패키지 설치

1
2
3
$ sudo apt-get install python3 python3-pip nginx
$ sudo pip3 install virtualenv
$ sudo pip3 install uwsgi

Virtualenv 설정

1
2
3
4
$ virtualenv .server
$ source .server/bin/activate
(.server) $ pip3 install flask
(.server) $ pip3 install uwsgi

uwsgi를 또 설치한 이유는 코드에서 uWSGI decorators를 사용하기 위함임

Flask 코드 작성

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# server.py
from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello():
    return 'world'

if __name__ == '__main__':
    app.run(host='0.0.0.0')

uWSGI 동작 확인

1
(.server) $ uwsgi --socket 0.0.0.0:5000 --protocol=http -w server --callable app --venv .server --master

5000번 포트 접속시 world 메세지가 잘 나오는지 확인. 잘 나온다면 virtualenv를 나오자

1
(.server) $ deactivate

uWSGI 설정 파일 작성

server.ini 파일을 아래와 같이 작성하자

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
[uwsgi]
strict = true

chdir = /home/pi/wallpad
venv = /home/pi/wallpad/.server
module = server
callable = app

master = true
processes = 1
threads = 3

socket = /tmp/server.sock
chmod-socket = 664
vacuum = true

die-on-term = true

log-4xx = true
log-5xx = true
disable-logging = true

strict : This option tells uWSGI to only allow valid uWSGI options in the config file chdir : the base directory (full path) venv : python virtualenv path module : python filename master : Respawns processes when they die and handles much of the built-in prefork+threading multi-worker management, generally always advised processes : Adds concurrency to the app by adding n additional processes threads : Adds additional cuncurrency by adding n additional threads socket : sock file path chmod-socket : permissions of the socket file vacuum : Removes the socket when the process stops die-on-term : If running the uWSGI service with the init system (systemd, upstart), confirms both uWSGI and the init system have the same idea about what each process signal means log-4xx : log requests with a 4xx response log-5xx : log requests with a 5xx response disable-logging : disable request logging

작성이 끝나면 아래 코드 실행후 /tmp/server.sock 파일이 생성되면 OK

1
$ uwsgi --ini server.ini

Nginx 설정

우선 default 파일을 삭제

1
$ sudo rm /etc/nginx/sites-enabled/default

그리고 /etc/nginx/sites-available 경로에 아래 파일 작성

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
server {
    listen 5000;
    server_name localhost;

    location / { try_files $uri @app; }

    location @app {
        include uwsgi_params;
        uwsgi_pass unix:/tmp/server.sock;
        uwsgi_ignore_client_abort on;
    }
}

작성이 끝나면 /etc/nginx/sites-enabled 경로에 작성한 파일을 심볼릭링크로 걸어줌.

1
$ sudo ln -s /etc/nginx/sites-available/server /etc/nginx/sites-enabled

nginx 설정파일 문법 확인후 재시작

1
2
3
4
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
$ sudo service nginx restart

Emperor 모드와 master 옵션간 문제

/home/pi/wallpad/uwsgi-emperor.log 파일을 보다보니 시작지점이 아래와 같은 WARNING 로그를 확인.

1
*** WARNING: you are running uWSGI without its master process manager ***

분명 나는 /etc/uwsgi/apps-available/server.ini 파일에 \'master = true\'라고 명시해줬다. 그런데 master process manager가 동작하지 않는다고?! 관련 내용을 찾아보니 아래와 같은 내용이 있었다.

The emperor should generally not be run with --master, unless master features like advanced logging are specifically needed. https://uwsgi-docs.readthedocs.io/en/latest/Emperor.html#notes

그리고 stackoverflow에도 질문 및 답변이 있었다. https://stackoverflow.com/questions/15055002/uwsgi-master-with-emperor-spawns-two-emperors

그리하여 emperor는 쓰지 않고 /etc/rc.local 파일을 아래와 같이 수정

1
$ /usr/local/bin/uwsgi --ini /home/pi/wallpad/server.ini

그리고 server.ini 파일에도 아래 3줄을 추가

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[uwsgi]
strict = true

chdir = /home/pi/wallpad
venv = /home/pi/wallpad/.server
module = server
callable = app

master = true
processes = 1
threads = 3

socket = /tmp/server.sock
chmod-socket = 664
vacuum = true

die-on-term = true

log-4xx = true
log-5xx = true
disable-logging = true

uid = www-data
gid = www-data

daemonize = /home/pi/wallpad/server.log
Hugo로 만듦
Jimmy의 Stack 테마 사용 중