코알못

5분 안에 구축하는 uWSGI (with. Flask, nginx) 본문

PYTHON

5분 안에 구축하는 uWSGI (with. Flask, nginx)

코린이s 2021. 7. 7. 19:47
728x90

uWSGI 가 무엇일까요 ?

WSGI 의 한종류로 'Web Server Gateway Interface' 로 알 수 있듯이 웹 서비스와 - 파이썬 통신을 위한 게이트 웨이 입니다

쉽게 말해 파이썬으로 된 코드는 웹 서버(nginx)를 붙이려면 통신할 수 있는 무언가가 필요한데 그 다리 역할을 하는 친구가 wsgi입니다

 

구축 해볼까요 ?

1. uwsgi 설치

- 환경에 맞게 설치 해주세요

# python 2
$ pip install uwsgi

# python 3
$ pip3 install uwsgi

# homebrew
$ brew install uwsgi

- 설치 확인 : 버전이 정상적으로 나오면 설치 성공!

$ uwsgi --version
2.0.19.1

 

2. 설정

- start.sh : 시작 스크립트

#/bin/bash

uwsgi --ini uwsgi.ini

- stop.sh : 종료 스크립트

#/bin/bash

uwsgi --stop ./uwsgi.pid

- uwsgi.ini : uwsgi 설정 파일

[uwsgi]
module=wsgi:app

processes=2
socket=./uwsgi.sock
chmod-socket=666
pidfile=./uwsgi.pid
daemonize=./logs/uwsgi.log

plugins-dir=/usr/local/Cellar/uwsgi/2.0.19.1_1/libexec/uwsgi
plugin=python3

log-reopen=true
die-on-term=true
master=true
vacuum=true

1) module 설정 의미는 파이썬 wsgi.py 에서 app 이라는 모듈을 실행하겠다는 의미

2) processes : 게이트 웨이 프로세스 2개를 띄우겠다는 의미 (실제로 프로세스 확인해보면 2개 띄워져 있다.)

3) socket, chmod-socket : 소켓 저장 경로와 권한을 설정한다.

4) pidfile : pid 파일 저장 경로 지정 한다.

5) daemonize : 로그 저장 경로 지정한다.

6) plugins-dir, plugin 은 파이썬 여러버전 설치 되어 있다면 지정 해줘야 실행이 되기 때문에 플러그인 지정 필요

: 저는 homebrew 로 uwsgi 설치 하였더니 plugins-dir 경로에 python 3 plugin 이 설치 되어 있었음

- wsgi.py : 만든 application 이라는 파이썬 코드를 실행시키는 코드

from application import app

if __name__ == "__main__":
    app.run()

- application.py : 실제 서비스할 Flask 앱

from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    return "Hello Flask"

* FLASK 앱은 아래 게시글에 있는걸 사용해도 됩니다.

:: FLASK 앱 샘플

3. 실행

$ ./start.sh

- 프로세스 확인

$ ps -ef | grep uwsgi
  501  5218     1   0  5:03PM ??         0:00.23 uwsgi --ini uwsgi.ini
  501  5219  5218   0  5:03PM ??         0:00.00 uwsgi --ini uwsgi.ini
  501  5220  5218   0  5:03PM ??         0:00.00 uwsgi --ini uwsgi.ini
  501  5222  2056   0  5:03PM ttys001    0:00.00 grep uwsgi

- uwsgi 로그 확인 : master 프로세스와 설정한 대로 프로세스 2개가 뜬다.

*** Starting uWSGI 2.0.19.1 (64bit) on [Sun Jul  4 13:09:35 2021] ***
compiled with version: Apple LLVM 12.0.0 (clang-1200.0.32.29) on 17 June 2020 09:03:34
os: Darwin-19.6.0 Darwin Kernel Version 19.6.0: Thu Jun 18 20:49:00 PDT 2020; root:xnu-6153.141.1~1/RELEASE_X86_64
nodename: hateyou.local
machine: x86_64
clock source: unix
pcre jit disabled
detected number of CPU cores: 12
current working directory: /Users/hongyoolee/document/study/uwsgi
writing pidfile to ./uwsgi.pid
detected binary path: /usr/local/Cellar/uwsgi/2.0.19.1_1/bin/uwsgi
your processes number limit is 2784
your memory page size is 4096 bytes
detected max file descriptor number: 256
lock engine: OSX spinlocks
thunder lock: disabled (you can enable it with --thunder-lock)
uwsgi socket 0 bound to UNIX address ./uwsgi.sock fd 3
Python version: 3.9.6 (default, Jun 29 2021, 06:20:32)  [Clang 12.0.0 (clang-1200.0.32.29)]
*** Python threads support is disabled. You can enable it with --enable-threads ***
Python main interpreter initialized at 0x7fe6bf008900
your server socket listen backlog is limited to 100 connections
your mercy for graceful operations on workers is 60 seconds
mapped 218736 bytes (213 KB) for 2 cores
*** Operational MODE: preforking ***
WSGI app 0 (mountpoint='') ready in 0 seconds on interpreter 0x7fe6bf008900 pid: 51068 (default app)
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI master process (pid: 51068)
spawned uWSGI worker 1 (pid: 51069, cores: 1)
spawned uWSGI worker 2 (pid: 51070, cores: 1)

 

4. nginx 설치

$ brew install nginx

- 설치 확인 : 버전이 나오면 성공!

$ nginx -v
nginx version: nginx/1.21.0

 

5. nginx 설정 : nginx.conf

- 일단 테스트를 위해 nginx 가 정상 동작하는지 확인

- homebrew 로 설치시 기본적으로 설정 파일이 만들어져 있다. (경로 : /usr/local/etc/nginx/nginx.conf)

- 설정 파일이 이미 만들어져 있다면 아래 설정 부분 찾아서 수정한다. (없다면 아래 git 주소에서 다운 받아 사용한다.) 

 server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        access_log  /usr/local/etc/nginx/logs/access.log;

        location / {
            root   html;
            index  index.html index.htm;
        }

- 아래 URL 로 접속하여 nginx 기능 테스트

- http://localhost:80/ 접속시 nginx 기본 페이지 나오면 성공

nginx 기본 페이지

- 파이썬 Flask 앱과 통신을 위해서는 uwsgi 에 설정 해둔 소켓과 통신하면 되므로 아래와 같이 수정한다.

- 경로는 소켓이 위치한 경로에 맞게 수정한다.

	location / {
		include uwsgi_params;
		uwsgi_pass unix:/Users/hongyoolee/document/study/uwsgi/uwsgi.sock;
	}

 

6. nginx 실행

# nginx start
$ nginx

# nginx stop
$ nginx -s stop

# nginx reload (순단 없이 수정 부분이 적용됨)
$ nginx -s reload

 

7. 최종 서비스 확인

- http://localhost:80/ 접속시  서비스 정상임을 확인 할 수 있다.

flask 동작 확인 완료

 

- 끝!!!! -

 

소스 파일은 아래 git 주소를 통해 다운 받아 사용 하면 됩니다 

:: https://github.com/works-code/py-uwsgi

 

works-code/py-uwsgi

uwsgi+nginx+flask 구성 스타터 코드. Contribute to works-code/py-uwsgi development by creating an account on GitHub.

github.com

 

위에 진행 하면서 오류 발생한 부분에 대해 정리 하였으니 같은 이슈 발생 하였을시 참고하세요 ㅎ

도움이 되기를 .... (별)

1. conda 환경의 python 과 pip 로 설치한 uwsgi 간의 호환이 안되는 경우

!!! UNABLE to load uWSGI plugin: dlopen(./python3.7_plugin.so, 10): image not found !!!
ImportError: dlopen(/Users/hongyoolee/miniconda3/lib/python3.7/lib-dynload/math.cpython-37m-darwin.so, 2): Symbol not found: _PyExc_MemoryError
  Referenced from: /Users/hongyoolee/miniconda3/lib/python3.7/lib-dynload/math.cpython-37m-darwin.so
  Expected in: flat namespace
 in /Users/hongyoolee/miniconda3/lib/python3.7/lib-dynload/math.cpython-37m-darwin.so
unable to load app 0 (mountpoint='') (callable not found or import error)
*** no app loaded. going in full dynamic mode ***
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI master process (pid: 46891)
spawned uWSGI worker 1 (pid: 46892, cores: 1)
spawned uWSGI worker 2 (pid: 46893, cores: 1)

*** no app loaded. going in full dynamic mode ***
spawned uWSGI master process (pid: 46891)
spawned uWSGI worker 1 (pid: 46892, cores: 1)
spawned uWSGI worker 2 (pid: 46893, cores: 1)

- 해결 방안 : pip install 이 아닌 다른 방법으로 uwsgi 설치 (저자는 homebrew 로 install 해서 해결 하였다)

- homebrew 가 없다면 conda 로 uwsgi install 도 가능 하다고 한다.

# uninstall
$ pip uninstall uwsgi

# homebrew 로 설치
$ brew install uwsgi

# conda 로 설치
$ conda install -c conda-forge uwsgi

 

2. 파이썬이 여러버전 설치 되어 있는 경우

*** Operational MODE: preforking ***
*** no app loaded. going in full dynamic mode ***
*** uWSGI is running in multiple interpreter mode ***
!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!
no request plugin is loaded, you will not be able to manage requests.
you may need to install the package for your language of choice, or simply load it with --plugin.
!!!!!!!!!!! END OF WARNING !!!!!!!!!!
spawned uWSGI master process (pid: 48920)
spawned uWSGI worker 1 (pid: 48921, cores: 1)
spawned uWSGI worker 2 (pid: 48922, cores: 1)

- 해결 방안 : 파이썬 버전을 uwsgi.ini 파일에 지정 해주거나, virtualenv 를 사용하여 파이썬 버전을 지정해준다.

1) uwsgi.ini 파일에 지정

plugins-dir=/usr/local/Cellar/uwsgi/2.0.19.1_1/libexec/uwsgi
plugin=python3

2) virtualenv : 실제 해보지는 않았으며 구글링해서 하시면 됩니다

 

3. 파이썬 3 사용하나 파이썬 2에 flask 설치 하여 3에서 찾을 수 없는 에러

*** Operational MODE: preforking ***
Traceback (most recent call last):
  File "/Users/hongyoolee/document/study/uwsgi/./wsgi.py", line 10, in <module>
    from application import app
  File "/Users/hongyoolee/document/study/uwsgi/./application.py", line 1, in <module>
    from flask import Flask
ModuleNotFoundError: No module named 'flask'
unable to load app 0 (mountpoint='') (callable not found or import error)
*** no app loaded. going in full dynamic mode ***
*** uWSGI is running in multiple interpreter mode ***

- 해결 방법 : 파이썬 3 에 install

$ pip3 install flask

 

# 참고

- nginx 설정 수정시 문법 오류가 있는지 확인

$ nginx -t
728x90
Comments