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

1. 필요 패키지 설치

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

2. Virtualenv 설정

$ virtualenv .server
$ source .server/bin/activate
(.server) $ pip3 install flask
(.server) $ pip3 install uwsgi

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

3. Flask 코드 작성

# 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')

4. uWSGI 동작 확인

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

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

(.server) $ deactivate

5. uWSGI 설정 파일 작성

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

[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

$ uwsgi --ini server.ini

6. Nginx 설정

우선 default 파일을 삭제

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

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

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 경로에 작성한 파일을 심볼릭링크로 걸어줌.

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

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

$ 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

7. Emperor 모드와 master 옵션간 문제

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

*** 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 파일을 아래와 같이 수정

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

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

[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

2개의 댓글

  1. 혹시 이 오류는 왜 생기는건지 알 수 있을까요?

    chdir() to project/
    chdir(): No such file or directory [core/uwsgi.c line 2592]
    chdir(): No such file or directory [core/uwsgi.c line 1613]

    uwsgi.ini파일을 실행하는 과정에서 생긴 오류이고, 해당 파일 내용은
    [uwsgi]
    module=app
    callable=app
    socket=project/uwsgi.sock
    chmod-socket=666
    plugin=python3
    chdir=project/

    log-reopen=true
    die-on-term=true
    master=true
    vacuum=true
    strict=true
    입니다. daemonize로 경로를 지정했을때도 No such file in directory 오류가 떠서 폴더를 생성했는데, 그래도 같은 오류가 떠서 ini파일에서 삭제했더니 저렇게 뜨고 실행이 안됩니다.
    출처: https://co-de.tistory.com/27 [코알못:티스토리]

    1. ByJJoon ByJJoon 댓글:

      chdir 옵션값을 상대경로가 아닌 절대경로로 작성해보시기 바랍니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다