brunch

You can make anything
by writing

C.S.Lewis

by 장영석 Jul 20. 2018

Quickstart uwsgi

Quickstart for Python/WSGI applications

Quickstart for Python/WSGI applications


빠른시작에서는 간단한 WSGI 애플리케이션과 일반적인 웹프레임워크를 어떻게 배포하는지 보여줄 것이다.


여기서 파이썬은 CPython을 의미한다, PyPy는 특정플러그인을 사용해야한다: PyPy plugin, Jython 지원은 준비중이다.


빠른시작을 따라가려면 최소 uWSGI 1.4 버전이 필요하다. 오래된 것은 더이상 유지관리가 되지 않으며 버그도 많다.


Installing uWSGI with Python support


uWSGI를 배우기 시작하면, 공식 소스에서 빌드하도록 하라: 배포판에서 제공되는 패키지를 사용하면 두통이 심하게 발생할 수 있다. 배포판에서 사용할 수 있는 것과 같은 모듈식 빌드를 사용할 수 있다.


uWSGI는 C 애플리케이션기 때문에, C 컴파일러(gcc 또는 clang 같은)와 Python development headers가 필요하다.


Debian 기반 배포판에서는

이면 충분하다.


다양한 방법으로 Python용 uWSGI를 설치할 수 있다.


via pip


using the network installer

(위 방식은 uWSGI를 /tmp/uwsgi에 설치한다, 자유롭게 변경해라).


via downloading a source tarball and "making" it


(빌드 후에 현재 디렉토리에 uwsgi 바이너리가 생긴다).


패키지 배포를 통한 설치는 다루지 않지만(모두가 행복할 수는 없다), 모든 일반적인 규칙이 적용된다.


배포판 패키지로 quickstart를 테스트를 할 때 한 가지 고려할 점은 아마도 배포판이 모듈 방식으로 구성되어 있을 거라는 점이다(모든 기능이 다른 플러그인으로 로드 되어야한다). quickstart를 완료하기 위해, 첫 번째 예제 전에 --plugin python,http를 사용하고, HTTP 라우터가 제거될 때 --plugin python을 사용해야한다. (너에게 이것이 이해가 되지 않는다면, 계속 읽어라).


The first WSGI application


간단한 "Hello World" 예제를 시작해보자.

(foobar.py로 저장해라).


보다시피, 단일 파이썬 함수로 구성되어있다. uWSGI Python 로더가 검색할 기본 함수로써 "application" 이라고 불린다(하지만 사용자정의 할 수 있다).


Deploy it on HTTP port 9090


이제 uWSGI를 시작해서 WSGI 애플리케이션으로 요청을 보내는 HTTP server/router를 실행해라.

이게 다다.


프론트엔드 웹 서버가 있거나 어떤 형태의 벤치마크가 있을 때 --http를 사용하지 않는다면 --http-socket을 사용해라. 이유를 알고 싶다면 quickstart를 계속 읽어라.


Adding concurrency and monitoring


첫 번째 튜닝은 동시성을 추가하는 것이다(uWSGI가 시작될 때 기본설정은 단일 프로세스와 단일 스레드다).


더 많은 프로세스를 추가하려면 --processes 옵션 또는 더 많은 스레드를 추가하고 싶다면 --threads 옵션을 사용해라.(또는 둘다 사용할 수 있다).

4개의 프로세스를 생성(각 프로세스별 두개의 스레드), 마스터 프로세스 (프로세스가 죽을 때 다시 프로세스를 생성한다) 그리고 HTTP 라우터(앞에서 본 것처럼)가 생성된다.


모니터링은 중요한 태스크 중 하나다. 프로덕션 배포에서 무엇이 진행중인지 이해하는 것은 중요하다. stats 서브시스템을 사용하면 uWSGI의 내부 통계데이터를 JSON으로 내보낼 수 있다.

> uwsgi --http :9090 --wsgi-file foobar.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191


앱에 몇가지 요청을 만들고 9191 포트로 텔넷을 연결하면 재미있는 정보를 많이 얻을 수 있다. 원한다면 인스턴스를 모니터링하기 위한 top과 같은 도구인 "uwsgitop"(단지 pip install)을 사용할 수 있다.


stats 소켓을 프라이빗 어드레스에 바인딩해라, 그렇지 않으면 모든 사람이 접근할 수 있다.


Putting behind a full webserver


uWSGI HTTP 라우터가 견고하고 고성능일지라도, 애플리케이션을 완벽한 웹서버 뒤에 배치할 수 있다.


uWSGI는 기본적으로 HTTP, FastCGI, SCGI를 지원하고 "uwsgi" 라는 이름의 특정 프로토콜을 사용한다. 최고의 수행 프로토콜은 분명히 uwsgi다. 이미 nginx와 Cherokee에서 지원한다.


일반적인 nginx 설정은 다음과 같다.

"모든 요청을 uwsgi 프로토콜을 사용하는 3031포트에 바인드된 서버에 전달해라"라는 뜻이다.


이제 우리는 uWSGI를 uwsgi 프로토콜을 사용하여 생성할 수 있다.

> uwsgi socket 127.0.0.1:3031 --wsgi-file foobar.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191


ps aux를 실행하면 하나의 프로세스가 전보다 하나 줄었을 것이다. HTTP 라우터는 "worker"(uWSGI에 할당 된 프로세스)가 uwsgi 프로토콜을 사용함으로써 제거되었다.

프록시/웹서버/라우터가 HTTP를 사용한다면, uWSGI에게 http 프로토콜을 사용하게해야한다.

if your proxy/webserver/router speaks HTTP, you have to tell uWSGI to natively speak the http protocol (프록시 자체를 생성하는 --http와는 다르다).

> uwsgi --http-socket 127.0.0.1:3031 --wsgi-file foobar.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191


Automatically starting uWSGI on boot

vi를 열고 uWSGI를 실행하기 위한 init.d 스크립트를 작성할 생각이라면, 관둬라. 너의 시스템이 더 나은 방법을 제공할 수 없다고 확신하지 마라.


각 배포판은 시작 시스템(Upstart, Systemd...)를 사용가능한 많은 프로세스 매니저들(supervisord, god, monit, circus...)이 있다.


uWSGI는 이것들 모두와 매우 잘 통합될 것이지만, 많은 앱을 배포할 계획이라면 uWSGI Emperor를 검토해라. - 이것은 모든 devops 엔지니어들의 꿈이다.


Deploying Django


Django는 아마도 Python 웹프레임워크중에 가장 많이 사용될 것이다. 배포하는것은 매우 쉽다. (우리는 4개의 프로세스와 각 2개의 스레드 설정으로 계속할 것이다).


우리는 /home/foobar/myproject에 Django 프로젝트가 있다고 가정한다.

> uwsgi --socket 127.0.0.1:3031 --chdir /home/foobar/myproject/ --wsgi-file myproject/wsgi.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191


(--chdir을 사용하여 특정 디렉토리로 이동한다). Django에서는 올바르게 모듈들을 로드하는 것이 필요하다.


아! 이게 뭐야? 그래 니가 옳아. 니가 옳아... 이러한 긴 명령어행을 다루는 것은 실용적이지 못하고 어리석고 오류를 내기 쉽다. 절대 두려워하지마! uWSGI는 다양한 설정 스타일을 지원한다. quickstart에서 우리는 .ini 파일을 사용할 것이다.

훨씬 낫군!

그냥 실행해.

 /home/foobar/myproject/myprojet/wsgi.py 파일이 없다면, 아마도 장고의 오래된 버전(< 1.4)을 사용하고 있을 것이다. 이러한 경우에는 조금 더 설정이 필요하다.

> uwsgi --socket 127.0.0.1:3031 --chdir /home/foobar/myproject/ --pythonpath .. --env DJANGO_SETTINGS_MODULE=myproject.settings --module "django.core.handlers.wsgi:WSGIHandler()" --processes 4 --threads 2 --stats 127.0.0.1:9191


또는 .ini 파일을 사용


장고의 오래된 버전(< 1.4) 에서는 env, module, pythonpath(myproject.settings 모듈에 도달 할 수 있또록) 설정이 필요하다.


A note on Python threads


스레드 없이 uWSGI를 시작한다면, Python GIL은 활성화되지 않으므로, 애플리케이션에서 생성된 스레드가 절대 실행되지 않을 것이다. 이런 선택을 좋아하지 않을수 있지만 uWSGI는 언어에 독립적인 서버라는 점을 기억해라, 그러므로 대부분의 그런 선택들은 그것들을 "불가지론"으로 유지하기 위함이다.


하지만 걱정하지마라, 기본적으로 uWSGI에서 개발자가 옵션으로 변경할 수 없는 항목은 없다.


애플리케이션에서 다중 스레드를 시작하지 않고 uwsgi에서 Python 스레드를 유지하길 원한다면 --enable-threads(또는 ini 스타일에서 enable-threads=true)  옵션을 추가하면 된다.


Virtualenvs


uWSGI는 특정 virtualenv에서 Python 모듈을 찾도록 설정될 수 있다.


옵션에 virtualenv = <path> 만 추가하면 된다.


Security and availability


uWSGI 인스턴스를 루트로 실행하지 마라. uid와 gid 옵션을 사용하여 권한을 없앨수 있다.

권한 있는 포트(HTTPS의 443 포트 같은)를 바인딩하려면, 공유 소켓을 사용해라. 권한이 삭제되기 전에 생성되고, =N 문법으로 참조할 수 있다. 여기서 N은 소켓 번호다(0부터 시작하는).


브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari