검색결과 리스트
글
예전에는 php 로 서버구성을 많이 하였는데, 요즘들어 개인적으로 Python 으로 서버를 돌려야 하는 일이 잦아졌습니다.
Tensorflow 로 학습한 AI 모델을 서비스 하기 위해서도 그렇고 - 물론 지금은 Tensorflow 가 Python 이외에도 지원합니다 - 개발 편의를 위해서 그렇기도 합니다.
DJANGO 와 WSGI 와 NGINX
Python 으로 웹서버(Server Side Script)를 개발하려고 하면 항상 나오는게 WSGI 입니다.
이 녀석은 Web Server Gateway Interface 의 약자이며, 예전에 cgi 그리고 php 의 fpm 과 비슷한 Gateway Interface 중 하나입니다. 당연히 Python 에서 사용하는 용어이며 Python 의 표준 Gateway Interface 입니다.
그리고 uWSGI 는 이 WSGI 을 Implementation 한 것입니다.
Python 의 웹 서비스 구조
일단 결론부터 말씀드리면 이렇습니다.
Python 은 다음 방법 중 하나를 통해서 클라이언트에게 서비스 할 수 있습니다.
- uWSGI 를 이용하여 포트로 서비스하는 방법
- uWSGI 를 이용하여 소켓으로 서비스하는 방법
- uWSGI 를 이용하여 Unix Socket 으로 서비스하는 방법
uWSGI 설치하기
Django 는 설치했다는 가정하에, uWSGI 를 설치합니다.
pip install uwsgi
# test.py
def application(env, start_response):
start_response('200 OK', [('Content-Type','text/html')])
return [b"Hello World"] # python3
#return ["Hello World"] # python2
uwsgi --http :8080 --wsgi-file test.py
그리고나서 8080 포트로 접속하면 Hello World 라는 문구를 볼수 있습니다.
Django 를 uWSGI 로 서비스하기
Django 의 프로젝트 폴더안에 있는 프로젝트명의 폴더를 보면, wsgi.py 파일이 들어 있을 것입니다.
이것을 uWSGI 로 서비스 하려면 다음과 같이 하면 됩니다.
저의 경우 프로젝트명이 html 입니다.
프로젝트의 전체 경로는 /home/crystalcube/html 이며 wsgi.py 파일은 /home/crystalcube/html/html/wsgi.py 에 위치합니다.
[crystalcube@host /home/crystalcube/html] uwsgi --http :8080 --module html.wsgi
Nginx 를 연동하기
일반적으로 안정적이고 빠른 웹서비스를 위해서, Nginx 앞단에 붙입니다.
최종적인 구조는 다음과 같을 것입니다.
[클라이언트] -> [Nginx] -> [unix Socket] -> [uWSGI] -> [Django]
uwsgi_params 라는 이름으로 파일을 하나 만듧니다.
uwsgi_param QUERY_STRING $query_string;
uwsgi_param REQUEST_METHOD $request_method;
uwsgi_param CONTENT_TYPE $content_type;
uwsgi_param CONTENT_LENGTH $content_length;
uwsgi_param REQUEST_URI $request_uri;
uwsgi_param PATH_INFO $document_uri;
uwsgi_param DOCUMENT_ROOT $document_root;
uwsgi_param SERVER_PROTOCOL $server_protocol;
uwsgi_param REQUEST_SCHEME $scheme;
uwsgi_param HTTPS $https if_not_empty;
uwsgi_param REMOTE_ADDR $remote_addr;
uwsgi_param REMOTE_PORT $remote_port;
uwsgi_param SERVER_PORT $server_port;
uwsgi_param SERVER_NAME $server_name;
nginx.conf 파일도 하나 만듧니다.
upstream django {
server unix:///sock/django.sock;
}
server {
listen 8080;
charset utf-8;
server_name _;
root /home/crystalcube;
location /images {
alias /home/data;
}
location /music {
root /sounds;
expires 1M;
add_header Cache-Control "public";
}
location / {
uwsgi_path django;
include /path/to/uwsgi_params;
}
}
이제 Nginx 의 config.d 폴더에 위의 nginx.conf 를 넣고 nginx 를 재시작 합니다.
nginx.conf 파일을 대략적으로 설명하자면,
server unix:///sock/django.sock;
uwsgi 를 port 가 아닌 unix socket 으로 실행할 것입니다.
그것이 성능면에서 우월합니다. 그리고 그 소켓의 위치는 /sock/django.sock 입니다.
root /home/crystalcube;
이 서비스의 root 경로입니다.
보안상 root 를 지정해 주는것이 좋습니다. 밖의 디렉토리/파일에 접근을 제한하기 위함입니다.
location /images {
alias /home/data;
}
location /music {
root /sounds;
expires 1M;
add_header Cache-Control "public";
}
알다시피 Django 는 static 파일에 대해서 서비스를 지원하지 않습니다.
Nginx 에서 static 파일을 serve 할 수 있는 방법이 크게 두가지인데, 하나가 alias 를 이용한 것이고 다른 하나가 root 를 이용한 것입니다.
두개의 차이를 설명하기 위해서 images 와 music 이라는 location 을 만들었습니다.
alias 는 위에 location 에 정의된 경로(/images)를 host 의 alias 경로로 변환한다고 생각하시면 됩니다.
예를들어 http://localhost:8080/images/1.jpg 인 경우, host 의 /home/data/1.jpg 에서 파일을 찾게 됩니다.
server 블록에 있는 root 에서 /home/crystalcube 라고 지정했는데, 이 부분은 alias 에서는 무시됩니다.
/music 을 살펴보면, root 를 sounds 로 지정하였습니다.
root 의 경우에는 location 에 정의된 경로(/music)의 root 를 지정한다고 생각하시면 됩니다.
다시말해 /music 이라는 url 에 대한 root 경로가 /sounds 이라는 뜻입니다.
그런데 이 server 블록에서 root 는 /home/crystalcube 이죠.
그러므로 location 이 music 인 경우, 이것의 최종적인 root 경로는 /home/crystalcube/sounds 가 되는 것입니다.
이건 어디까지나 root 의 경로이므로 서비스 경로는 /home/crystalcube/sounds/music 이 됩니다.
예를들어 http://localhost:8080/music/1.mp3 의 host 경로는 /home/crystalcube/sounds/music/1.mp3 가 됩니다.
요컨데 alias 의 값은 server의 root 는 무시한 절대적인 경로로 대체됩니다.
root 는 'server 의 root 경로' + 'root 경로' + 'location 경로' 가 됩니다.
expires 와 add_header 는 Cache 를 넣기 위한 것입니다.
웬만해서 변할일이 없는 static 파일은 캐시를 넣어 주는것이 좋겠지요.
이제 uWSGI 가 Unix Socket 을 통해서 Django 를 서비스 하도록 해 봅시다.
nginx 를 다시 실행해 줍니다.
sudo systemctl reload-daemon
sudo systemctl restart nginx
그리고 uWSGI 를 실행합니다.
uwsgi --socket /sock/django.sock --module html.wsgi --chmod-socket=666
제대로 동작하고 있는지 8080 포트로 접속을 해 봅니다.
서비스 구조는 앞서 말씀드린대로 다음과 같습니다.
[클라이언트(브라우저)] -> [Nginx] -> [Unix Socket] -> [uWSGI] -> [Django]
uWSGI 서비스 등록하기
먼서 uWSGI 를 서비스에 등록하기 위해서, 커맨드 라인으로 실행하던 것을 ini 파일로 만드는 것이 편합니다.
uwsgi.ini 라는 이름으로 파일을 만듧니다.
[uwsgi]
chdir = /home/crystalcube/html
module = html.wsgi
master = true
processes = 10
socket = /sock/django.sock
chmod-socket = 666
vacuum = true
테스트를 위해서 이것을 실행하려면 다음과 같이 하면 됩니다.
uwsgi --ini ./html/uwsgi.ini
이제 이것을 system daemon 으로 등록합니다.
저의 경우 /etc/systemd/system/django.service 라는 이름으로 했습니다.(대충대충..)
[Unit]
Description=Crystalcube Sample
After=network.target
[Service]
User=crystalcube
Group=crystalcube
Environment=LOG_PATH=/home/crystalcube/logs # Just sample
WorkingDirectory=/home/crystalcube/html
ExecStart=/usr/bin/uwsgi --ini ./html/uwsgi.ini
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl start django.service
이제 8080 포트를 통해서 접근하면, 정상적으로 동작할 것입니다.
시스템이 재부팅 될때마다 자동으로 실행하려면, 시스템 데몬에 enabled 로 등록해 주시면 됩니다.
일일이 설명한다는게 여간 힘든게 아니네요.
이번 글은 날림으로 작성하였습니다. ㅎ...
'Python' 카테고리의 다른 글
Python 시작하기 (0) | 2011.02.12 |
---|
RECENT COMMENT