Nginx란?
•
경량화된 소프트웨어 웹 서버이다.
•
웹서버란 인터넷 네트워크 위에서 HTTP 프로토콜을 이용해 HTML, CSS, Javascript, image/mediafile과 같은 정적인 정보들을 웹 브라우저에 전송한다.
•
Nginx는 Single-thread로 동작하며 비동기 non-blocking I/O 이벤트 기반으로 요청을 처리한다. 따라서 적은 자원으로 효율적인 트래픽 처리가 가능하다.
•
멀티 스레드를 사용한다면 요청이 들어올 때마다 스레드가 생성되고 context-switching 횟수가 증가하므로 자원이 낭비될 수 있다.
Nginx의 기능
•
HTTP Server로서 정적 파일을 Serve 해준다
◦
클라이언트(유저)로부터 요청을 받았을 때 WAS를 거치지 않고 요청에 맞는 정적 파일을 응답해주는 HTTP server로서 활용할 수 있다.
◦
HTML, CSS 같은 정적인 리소스에 대한 요청을 Nginx가 처리해준다.
◦
React의 build 된 파일들도 정적인 리소스라고 볼 수 있고 따라서 Nginx가 index.html 같은 메인 페이지를 랜더링 해줄 수 있다.
•
Reverse Proxy Server로서 Client와 Server를 중개해준다.
◦
Reverse Proxy Server로서 Client의 Request와 Server의 Response를 중계하는 서버로 동작하게 할 수 있다. 이 과정에서 nginx는 로드밸런서로서의 역할을 수행할 수 있다.
◦
동적으로 계산되거나 전달되어야 하는 사항들은 WAS에게 맡긴다.
Apache와 다른 점
•
Apache와 같은 웹서버는 클라이언트로부터 받은 요청을 처리할 때 새로운 프로세스 또는 쓰레드를 생성하여 처리합니다.
•
요청마다 쓰레드가 생성되므로 접속하는 사용자가 많으면 그만큼 쓰레드가 생성되어 CPU와 메모리 자원의 소모가 커집니다.
•
Nginx는 Event-Driven 구조로 동작하기 때문에 한 개 또는 고정된 프로세스만 생성하여 사용하고, 비동기 방식으로 요청들을 Concurrency 하게 처리할 수 있습니다.
•
위의 그림에서 보이듯이 Nginx는 새로운 요청이 들어오더라도 새로운 프로세스와 쓰레드를 생성하지 않기 때문에 프로세스와 쓰레드 생성 비용이 존재하지 않고, 적은 자원으로도 효율적인 운용이 가능합니다.
•
이러한 Nginx의 장점 덕분에 단일 서버에서도 동시에 많은 연결을 처리할 수 있습니다.
Nginx의 구조
•
Nginx는 하나의 Master Process와 다수의 Worker Process로 구성되어 실행됩니다.
•
Master Process는 설정 파일을 읽고, 유효성을 검사합니다. 그리고 Worker Process를 관리합니다.
•
모든 요청은 Worker Process에서 처리합니다.
•
Nginx는 이벤트 기반 모델을 사용하고, Worker Process 사이에 요청을 효율적으로 분배하기 위해 OS에 의존적인 메커니즘을 사용합니다.
•
Worker Process의 개수는 설정 파일에서 정의되며, 정의된 프로세스 개수와 사용 가능한 CPU 코어 숫자에 맞게 자동으로 조정됩니다.
Proxy Server
•
클라이언트가 데이터를 요청하면 중간에 클라이언트의 요청을 서버로 보내주는 Proxy라고 불리는 서버가 하나 존재한다.
•
클라이언트와 서버가 서로 직접적으로 통신하지 않고, 프록시 서버를 이용해서 리소스를 전달하며 보안, 트래픽 분산, 캐시 사용(속도 향상) 등 여러 장점을 가지는 중요한 서버이다.
Forward Proxy
•
클라이언트가 외부 인터넷에 직접 접근하는 것이 아니라
Proxy Server에 외부 인터넷 접근 요청을 하고
Proxy Server가 외부 인터넷에 대신 접속하여 결과를 받은 후
클라이언트에 전달하는 서버
•
포워드 프록시 방식은 정해진 사이트에만 연결이 가능하게끔 설정이 가능해서
주로 회사 내부의 인트라넷 등 보안이 중요한 환경에서 주로 사용된다.
Reverse Proxy
•
클라이언트가 Reverse Proxy에 요청하면
Reverse Proxy가 관련 요청에 따라 적절한 내부 서버에 접속하여
결과를 받은 후 클라이언트에 전달하는 서버
•
리버스 프록시 서버는 실제 서버가 어디서 동작하는지 감추는 역할을 한다.
클라이언트는 리버스 프록시를 통해서 리소스를 요청하기 때문에 서버의 IP주소를 알 수 없다.
그리고 리버스 프록시 서버는 실제 서버들에 대한 주소를 매핑하고 있어야 한다.
Nginx에서 제공하는 로드밸런싱 방법
•
Round Robbin
◦
운영체제 스케줄링 방법에도 있는 방식이다. 주어진 서버들을 순차적으로 돌아가면서 선택하는 방법이다.
•
Least-connected
◦
현재 접속자 수가 가장 적은 서버를 선택하는 방법이다.
•
ip-hash
◦
hash function을 사용해서 클라이언트 ip를 hash 한 결과에 따라서 다른 서버를 할당해주는 방법이다.
nginx.conf 설정
•
nginx가 작동하는 방식을 결정하는 구성파일로 /etc/nginx/nginx.conf 이 위치에 존재
•
크게 user, worker_processes, pid, events, http 항목으로 이루어짐
•
sites-enabled 폴더는 sites-available 폴더의 심볼릭 링크 폴더
•
sites-available 폴더에 파일을 작성하면 sites-enabled 폴더에 넣어진 것으로 보고 nginx.conf의 http 항목에서 include를 통해 설정이 적용됨
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
use epoll;
}
http {
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_arrd - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
client_max_body_size 75M;
server_tokens off
upstream docker-nginx {
server nginx:80;
}
upstream docker-apache {
server apache:80;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
...
root /var/www/html;
...
index index.html index.htm index.nginx-debian.html;
...
server_name _;
...
location / {
try_files $uri $uri/ =404;
...
rewrite regex URL break;
...
proxy_pass http://docker-apache;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
Shell
복사
•
user
◦
worker 프로세스를 실행할 사용자를 설정하고 이 사용자에 따라 권한이 달라질 수 있다.
•
worker_processes
◦
이벤트를 처리하는 프로세스의 수를 정의하는 지시어이다.
◦
일반적으로 CPU의 core 수만큼 할당하고, auto로 설정하면 자동으로 값을 알맞게 설정
•
error_log
◦
오류 로그를 남길 파일 경로 지정
•
pid
◦
NGINX 마스터 프로세스 ID 를 저장할 파일 경로 지정
•
events
◦
worker_connections
▪
하나의 프로세스가 동시에 몇 개의 연결을 처리할 수 있는지 설정해준다
▪
보통 512 또는 1024로 설정한다
◦
use
▪
Linux에서 socket을 관리하는 데 사용하는 방식
▪
epoll : 현재 활성화 된 소켓만 확인해서 연결을 설정
▪
poll : 해당 프로세스에 연결된 모든 connection file을 스캔
▪
select : 해당 프로세스에 연결된 모든 connection file을 스캔
•
http
◦
include
▪
파일을 읽어들임
◦
default_type
▪
기본 MIME 타입 설정
◦
log_format
▪
엑세스 로그 포멧 설정
◦
access_log
▪
엑세스 로그 저장경로
◦
sendfile
▪
응답을 보낼 때 user 영역 buffer가 아닌 kernel file buffer를 사용
◦
keepalive_timeout
▪
타임아웃 시간 설정
◦
client_max_body_size
▪
nginx를 통해서 이동하는 파일의 최대 크기를 지정해 줄 수 있는 지시어
◦
server_tokens
▪
nginx 버전을 숨길 수 있다. (보통 숨기는게 일반적)
◦
upstream
▪
컨테이너별 server 설정
◦
server
▪
listen
•
listen은 HTTP 요청을 받을 포트를 설정
•
default_server는 모든 웹서버 요청을 받는다는 의미
•
두번째 listen은 IPv6 포트 관련 설정
▪
root
•
요청이 왔을 때 응답해줄 HTML 파일이 있는 폴더의 경로
▪
index
•
HTML 파일의 이름 리스트 (앞에서부터 찾음)
▪
server_name
•
요청을 받을 도메인 이름 설정
•
localhost나 별도 도메인 이름이 없다면 기본 설정
▪
location
•
URI에 대한 파일을 찾고 없다면 404 응답을 하는 설정
•
location 문단을 추가하며 URI 매핑 가능
•
location 문단 내에 root 설정 가능
•
rewrite를 통해 내부 서버에 요청할 URL을 변경할 수 있음
•
proxy 설정은 실제 클라이언트의 정보를 내부 서버에 전달하기 위한 설정
error_page 설정
error_page 403 404 405 406 411 497 500 501 502 503 504 505 /error.html;
location = /error.html {
root /usr/share/nginx/html;
}
Shell
복사
캐시 설정
location ~* \.(ico|css|js|gif|jpe?g|png)$ {
expires max;
add_header Pragma public;
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
}
Shell
복사
Nginx 명령
$ service nginx restart #재시작
Shell
복사
nginx.conf 샘플
#유저, 권한 설정
user nginx;
#worker process의 수 설정
worker_processes auto;
#daemon 설정
daemon off;
#error log 경로와 master process의 경로 설정
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
#네트워크 작동환경 설정
events {
#한 개의 worker process가 동시에 처리할 수 있는 connection의 수
worker_connections 1024;
}
#http 관련 설정
http {
#mime.types 파일 불러오기
include /etc/nginx/mime.types;
#기본 타입 설정
default_type application/octet-stream;
#엑세스 로그 포맷 설정
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
#엑세스 로그 경로 설정
access_log /var/log/nginx/access.log main;
#sendfile api 설정
sendfile on;
#타임아웃 시간 설정
keepalive_timeout 65;
#nginx 버전 가리기
server_tokens off;
#호스트 설정
server {
#http 요청을 받을 포트 설정(default_server는 모든 서버로부터 요청 받음)
listen 80 default_server;
#IPv6에 대한 설정
listen [::]:80 default_server;
#요청을 받을 도메인 이름 설정
server_name _;
#URI 매핑 설정
location / {
#지원되지 않는 HTTP 메소드 차단
if ($request_method !~ ^(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)$) {
return 405;
}
proxy_pass http://localhost:8080;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
JavaScript
복사