본 문서는 패스트캠퍼스 ‘Web-Programming School’ 수업 자료를 바탕으로 작성되었습니다.
동작 방법
- 기존
Browser(Client) -> runserver -> Djnago <===> PostgresSQL
- EC2
Browser(Client) ->
<!-- AWS의 설정 -->
(SecurityGroup) -> EC2(Port:80)->
<!-- EC2 내부에서의 설정 -->
Nginx(WebServer)-> uWSGI(Web server gateway interface) -> Django
EC2 runserver
EC2 -> -> Django(:8000)
EC2 -> uWSGI(:8000) -> Django(wsgi모듈)
EC2 -> Nginx(Nginx virtual server) <->(Unix Socket) uWSGI -> Django
EC2 -> Djnago(:8000)
>> ./manage.py runserver 0:8000
EC2 -> uWSGI(:8000) -> Django(wsai모듈)
WSGI(Web server gateway interface)란?
웹서버와 웹 애플리케이션의 인터페이스를 위한 파이썬 프레임워크다. 상식대로 웹 서버 위에 서버 어플리케이션이 올라가는데 이 어플리케이션과 웹 서버간의 커뮤니케이션을 위해 wsgi 미들웨어가 존재하는 것. 출처:khanrc’s blog
WSGI
웹서버마다 요청이 다르기 때문에 중간에서 규격을 맞춰주는 인터페이스가 WSGI 그리고 규격에 맞는 것 웹 애플리케이션으로 넘겨줌
웹 서버 (Nginx) 같은 것을 의미함 / 이미지나, 텍스트와 같은 정적 파일을 처리
웹 애플리케이션 동적 파일 처리 (Django까지 감)
장고_uWSGI
runserver
명령어는 WSGI_APPLICATION
으로부터 읽어서 실행한다. 기본적으로
- uWSGI 정상 동작 확인
>> pip install uwsgi
<!-- 명령어 -->
uwsgi \
--http :(port) \
--home (virtualenv경로) \
--chdir <django프로젝트 경로> \
-w <설정 패키지명>.wsgi
>> uwsgi \
--http :8000 \
--home /home/ubuntu/.pyenv/versions/runserver-tset \
--chdir /srv/runserver-test/mysite \
--module mysite.wsgi
EC2 -> Nginx(Nginx virtual server) <->(Unix Socket) uWSGI -> Django
Nginx
- 최신 버전 설치(작성 당시의 경우, 1.12.2) 설치
>> sudo -s
>> nginx=stable # use nginx=development for latest development version
>> add-apt-repository ppa:nginx/stable
>> apt-get update
>> apt-get install nginx
EC2 -> Nginx ->x uWSGI -> Django
Nginx 에서 80번포트로 접근할 수 있도록 인바운드 설정 뒤, 주소에서 8000번 포트를 지우고 들어가면 아래와 같은 그림을 확인 할 수 있다.
EC2 -> Nginx <->(Unix Socket) uWSGI-> Django
유닉스 도메인 소켓(Unix Domain Socket)은 프로세스간의 데이터 교환을 위한 기술 중 하나로, 파일 시스템을 통해 소켓통신 방식으로 내부 프로세스간의 통신을 하는 구조로 이뤄져있다. 약칭으로 UDS라고 표기하며, 간단하게 ‘유닉스 소켓(Unix socket)‘이라고 부르기도 한다. IPC(Inter Process Communication)의 일부로서 분류할 때는 ‘IPC소켓’이라고 부르기도 한다.
UDS의 가장 큰 특징은 소켓통신 방식을 써서 만든 프로세스에 사용이 가능하기 때문에 소켓프로그래밍 구조를 유지한 채로 로컬 프로세스와의 효율적 통신을 가능케 한다는 점이다. TCP, 혹은 UDP형식 데이터를 파일 시스템을 이용해서 통신하는 구조로, 파일 시스템을 통해 파일 주소 및 inode로 각 프로세스에서 참조되며, 통신은 운영체제의 커널상에서 이뤄지기 때문에 inet소켓을 이용해서 네트워크단을 이용해 전달하는 것보다 빠르며 부하가 적게 걸린다. 참고
- http 전달 과정에서 많은 패킷이 필요로한다. 그래서 컴퓨터내에서 좀 더 효율적인 방법으로
Unix Socket
을 사용한다 - uwsgi를 소켓 모드로 실행
>> /home/ubuntu/.pyenv/versions/runserver-test/bin/uwsgi \
--socket /tmp/app.sock \
--home /home/ubuntu/.pyenv/versions/runserver-test \
--chdir /srv/runserver-test/mysite \
--module mysite.wsgi \
--vacuum
- 위 명령어를 실행되는 동안에는
/tmp/app.sock
이 보인다.
uwsgi 설정
- uwsgi를 실행시키기 위한 명령어를 항상 쓰기엔 번거롭다(길어..ㅜㅜ) 그래서 uwsgi파일 설정과 Service 설정을 해보자
uwsgi 파일 설정
uwsgi.ini
에 아래 설정을 입력하고 저장한 뒤, uwsgi를 실행하면 welcome 페이지 뜨는지 확인
>> /srv/runserver-test/
>> vi uwsgi.ini
<!-- vi uwsgi.ini -->
;runsever-test uwsgi setting file for Django project
[uwsgi]
chdir = /srv/runserver-test/mysite
module = mysite.wsgi
home = /home/ubuntu/.pyenv/versions/runserver-test
socket = /tmp/app.sock
master = true
vacuum = true
;logto = /tmp/uwsgi.log
;log-reopen = true
>> /home/ubuntu/.pyenv/versions/runserver-test/bin/uwsgi \
--ini /srv/runserver-test/uwsgi.ini
uwsgi 서비스 설정
Service : 우리가 직접 실행한 프로그램이 아닌, 백그라운드에서 실행되고 있는 프로세스 Nginx의 경우에는 기본적으로 서비스에 등록되있지만, uWSGI는 아니다.
- /etc/systemd/system/uwsgi.service파일에 서비스 내용을 작성
- sudo systemctl enable uwsgi로 uwsgi.service를 서비스에 등록
- sudo systemctl daemon-reload로 systemctl에 등록된 서비스 내용이 바뀌었을 경우 적용
- sudo systemctl restart uwsgi로 uwsgi서비스를 재시작
- 홈페이지 접속이 잘되는지 확인! (장고 Welcome보이면 정상작동)
오류가 뜨는 경우sudo systemctl status uwsgi.service
확인
>> /etc/systemd/system
>> sudo vi uwsgi.service
<!-- vi uwsgi.service -->
[Unit]
Desciption = EC2 Deploy uWSGI service
After = syslog.target
[Service]
ExecStart = /home/ubuntu/.pyenv/versions/runserver-test/bin/uwsgi -i /srv/runserver-test/.config/uwsgi.ini
Restart = always
KillSignal = SIGQUIT
Type = notfiy
StandardError = syslog
NotifyAccess = all
[Install]
WnatedBy = multi-user.target
>> sudo cp -f /srv/runserver-test/uwsgi.service \ /etc/systemd/system/uwsgi.service
>> sudo systemctl enable uwsgi
>> sudo systemctl daemon-reload
>> sudo systemctl restart uwsgi
Nginx 가상 서버 설정
- 하나의 IP로 웹 서버에서 여러 도메인을 연결해서 서비스를 하기 위해선 가상 호스트를 설정해야 한다.
<!-- /tmp cd /etc/nginx/sites-available/default -->
listen 80 default_server;
listen [::]:80 default_server;
- 기본적으로 80번 요청이 들어왔을 때, 특정 도메인이 아닌 경우엔 디폴트 서버가 처리
>> sudo vi app
<!-- /tmp cd /etc/nginx/sites-available/app 생성-->
server {
listen 80;
server_name *.amazonaws.com;
charset utf-8;
client_max_body_size 128M;
location / {
uwsgi_pass unix:///tmp/app.sock;
include uwsgi_params;
}
}
listen 80
: 80 번 포트의 요청을 받겠다.server_name
:.amazonaws.com
으로 끝나는 주소로 들어오는 요청을 받겠다.location
:.amazonaws.com
의 주소의 요청을tmp/app.sock
이라는 파일에 담아uWSGI
과 통신하겠다는 의미
설정파일 심볼릭 링크 생성
심볼릭 링크의 경우, 단순히 원본파일을 가리키도록 만든 것이다. 원본파일만 가리키고 있기 때문에 원본파일의 크기와는 무관하고, 원본 파일이 삭제되면, 링크파일이 깜빡거리면서 원본이 없다는 것을 알려준다
<!--위치 : /etc/nginx/sites-enabled -->
>> sudo ln -s ../sites-available/app app
lrwxrwxrwx 1 root root 34 Mar 2 15:51 default -> /etc/nginx/sites-available/default
<!-- 설정을 적용하기 위해서 -->
>>sudo systemctl restart nginx
이렇게 하면…. 원래 되야하는데 502 Bad GateWay
에러가 났다.
>> cd var/log/nginx
>> cat error.log
(13: Permission denied) while connecting to upstream
<!-- 어떤 유저에 의해서 nginx가 실행되는지 알아보기 위한 명령어 -->
>> ps -axu | grep nginx
root 3138 0.0 0.1 150168 1572 ? Ss Mar02 0:00 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
<!-- nagix가 기본적으로 실행될 때 실제 프로세스 실행 시키는 유저 -->
www-data 3144 0.0 0.3 150564 3308 ? S Mar02 0:00 nginx: worker process
<!-- 이 명령어는 우리가 실행한것으로 한번 실행하고 사라짐 -->
ubuntu 5155 0.0 0.0 12916 936 pts/1 R+ 04:56 0:00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn nginx
- ps 명령어 : 현재 시스템에서 돌고있는 프로세스를 보여주는 가장 기본적인 명령어
nginx 실행 프로세서 사용자 설정
- uwsgi와 통신하는 app.sock의 경우 ubuntu유저 외 다른 유저는 실행이 불가하다. 그래서 nginx 실행시키는 유저를 ubuntu 로 바꾸자
>> cd /tmp/
srwxrwxr-x 1 ubuntu ubuntu 0 Mar 3 04:53 app.sock
>> cd /etc/naginx/
>> sudo vi nginx.conf
<!-- /etc/nginx/nginx.conf -->
user ubuntu;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
>>sudo systemctl restart nginx
그리고 다시 브라우저에 접속을 하면 502 GateWay
오류가 아닌 장고 welcome 페이지를 볼 수 있다!
결론 EC2 -> Nginx(Nginx virtual server) <->(Unix Socket) uWSGI -> Django
접속 완료