1. Nginx란?
Nginx는 오픈소스 소프트웨어 웹서버로 시작되었습니다. 지금은 웹서버의 역할뿐만 아니라 프록시 서버, 캐싱, 분산 처리, 미디어 스트리밍 등을 위한 다양한 기능을 제공합니다.
기능뿐만 아니라 성능면에서 기존의 웹서버들보다 뛰어나 현재 Nginx는 가장 널리 사용되고 있는 웹 서버입니다.
Nginx가 등장하기 전 웹서버의 대표 주자였던 Apach보다 어떤 점이 좋아서 현재 가장 많이 사용되는 웹서버로 자리 잡았는지 동작원리를 비교해 봅시다.
2. Nginx / Apach
a. Apach 동작 원리
Apach 이전에 웹서버로 사용되던 NCSA HTTPd가 있었습니다. 하지만 버그가 많이 발생해서 사용하는데 불편한 점이 많았고 이러한 문제점을 해결하기 위해 나온 웹서버가 Apach입니다. 지금부터 Apach의 동작 원리를 살펴봅시다.
a-1. 요청마다 새로운 process를 생성
Apach는 각 요청마다 새로운 프로세스를 생성하여 요청을 처리합니다. 요청마다 독립적인 메모리 공간을 사용하기 때문에 안정적이지만, 요청 수가 많아질수록 메모리에 부하가 발생합니다.
a-2. PREFORK 방식
요청을 처리하기 위해 요청마다 프로세스를 생성하면 그에 따른 비용이 발생하기 때문에 PREFORK라는 방식을 사용하여 미리 프로세스를 만들어놓고, 요청이 들어오면 프로세스를 할당하는 방식으로 동작합니다. 쉬고 있는 프로세스가 없을 경우에 프로세스를 새로 생성해서 요청을 처리하는 방식입니다.
a-3. 확장성 - 동적 콘텐츠
Apach는 요청마다 독립적인 프로세스를 처리하는 구조 덕분에 다양한 모듈을 만들어서 서버에 빠르게 기능을 추가할 수 있었습니다. 확장성이 높고, 동적인 콘텐츠도 처리할 수 있어서 다양한 웹 애플리케이션 환경에서 유연하게 사용할 수 있었습니다.
b. Apach 문제점
컴퓨터 보급이 증가함에 서버의 연결 요청 connection이 급격하게 증가하면서, Apach는 프로세스 기반 구조로 인해 요청에 대한 새로운 연결을 처리하지 못하는 문제가 발생했습니다.
b-1. 메모리 부하
매 요청마다 새로운 프로세스를 생성하므로, 메모리 사용량이 증가로 인해 새로운 연결을 처리하지 못하는 문제가 발생했습니다. => C10K(Connection 10000 Problem)
💡C10K(Connection 10000 Problem)란
동시에 10,000개의 연결을 처리하는 문제"를 의미하며, 서버가 동시에 다수의 클라이언트 요청을 처리할 때 발생하는 성능 문제를 설명하는 용어이다.
b-2. 컨텍스트 스위칭으로 인한 CPU 부하
많은 프로세스가 생성되면, CPU는 각 프로세스 간의 컨텍스트 스위칭을 많이 하게 되어 CPU에 부하가 증가합니다.
Apach도 이러한 문제점을 구조적으로 개선하기 위해 Worker MPM이란 구조를 추가되었습니다. Worker MPM은 프로세스 기반이 아닌, 각 프로세스 내에서 쓰레드를 사용하여 요청을 처리하는 방식입니다.
각 프로세스가 다수의 쓰레드를 사용하므로, 메모리 사용량은 줄어들지만 성능 문제는 완전히 해결하지는 못했습니다.
💡컨텍스트란
프로세스나 스레드가 실행되는 동안의 상태를 의미이다.
💡컨텍스트 스위칭이란
CPU가 하나의 프로세스나 스레드에서 다른 프로세스나 스레드로 전환될 때 발생하는 작업입니다.
c. Nginx 동작원리
Apach의 구조적인 문제와 해결하기 위해 Nginx가 등장했습니다. Nginx는 요청에 대한 connection을 효율적으로 처리할 수 있는 구조로 설계되었습니다. 하지만 Nginx는 동적인 콘텐츠를 직접 처리할 수 없었습니다.
Nginx는 클라이언트의 요청에 대한 Connection을 유지하고, 정적 콘텐츠는 직접 처리하고, 동적 콘텐츠에 대한 요청은 Apach에 전달하여 부하를 줄일 수 있습니다.
Nginx가 어떻게 많은 Connection을 유지할 수 있는지 동작 원리를 살펴봅시다.
c-1. master - worker process
Nginx는 master - worker 프로세스 모델을 사용합니다.
- Master 프로세스: 설정 파일을 읽고, worker 프로세스를 생성하고 관리합니다.
- Work 프로세스: 실제로 클라이언트 요청을 처리하는 프로세스입니다.
💡worker 프로세스 확인 및 수정
1. worker 프로세스 확인ps aux --forest
2. worker 프로세스 수정cd /etc/nginx/ sudo vim nginx.conf -> worker_processes 2; //auto -> 2로 수정 sudo systemctl restart nginx ps aux --forest
c-2. event driven
Nginx는 비동기 이벤트 기반 모델을 사용하며, 각 요청을 이벤트 루프를 사용하여 I/O 작업을 논블로킹 방식으로 수행합니다. => 하나의 work 프로세스가 수 천 개의 연결을 동시에 처리할 수 있어, CPU 메모리 사용을 최대한 효율적으로 사용합니다.
d. Nginx 장단점
장점
- 클라이언트의 동시 요청을 최대한 효율적으로 처리할 수 있습니다. => event driven
- 웹 서버의 역할뿐만 아니라 프록시 서버, 캐싱, 분산 처리 등 다양한 기능을 제공합니다.
단점
- 동적 콘텐츠를 직접 처리할 수 없습니다.
- 그로 이한 동적 콘텐츠를 제공하기 위해서는 외부 자원과 연동해서 사용해야 합니다.
3. Nginx 용도
a. 웹 서버 (web server)
정적 콘텐츠(HTML, CSS, Javascript, 이미지 등)를 제공할 수 있는 웹 서버의 역할을 할 수 있습니다.
b. 프록시 서버 (Proxy server)
b-1. Forward Proxy
클라이언트와 웹 서버 사이에서 클라이언트 측에 가까운 위치에 있는 프록시 서버입니다. 클라이언트가 요청을 보낼 때, 직접 목적지 서버에 접속하지 않고 포워드 프록시를 통해 요청을 전달합니다.
기능
- 캐싱: 자주 요청되는 외부 콘텐츠(외부 서버에서 요청받는 콘텐츠)를 캐싱하여, 응답 속도를 높일 수 있습니다.
- 익명화: 외부 서버는 클라이언트의 IP 주소를 알 수 없으므로 익명성을 유지합니다.
b-2. Reverse Proxy
클라이언트와 웹 서버 사이에서 서버 측에 가까운 위치에 있는 프록시 서버입니다. 클라이언트가 특정 웹 서버에 요청을 보내면, 리버스 프록시가 요청을 받아 실제 서버에 전달하고 응답을 클라이언트에게 다시 전달합니다.
기능
- 보안: 클라이언트가 백엔드 서버로 직접 접근하지 못하게 하여, 서버를 외부로부터 보호할 수 있습니다.
- 로드 밸런싱: 여러 백엔드 서버로 트래픽을 분산하여 서버 부하를 균형 있게 처리할 수 있습니다.
- SSL 터미네이션: HTTPS 요청을 Nginx에서 처리하고, 백엔드로 전달할 때 HTTP 프로토콜로 전달합니다. => SSL/TLS 처리를 Nginx에서 처리하여, 백엔드에서의 복호화에 대한 부담을 줄여줍니다.
- 캐싱: 자주 요청되는 콘텐츠를 캐싱하여, 백엔드의 부담을 줄여주고 응답 속도를 높입니다.
4. Nginx 환경 설정
Nginx의 설정 파일은 기본적으로 /etc/nginx/nginx.conf 또는 /etc/nginx/conf.d/*.conf에 위치합니다. 해당 경로로 이동해서 설정 파일을 용도에 맞게 작성할 수 있습니다.
웹서버 설정 예시
server {
listen 80; # HTTP 포트
server_name example.com www.example.com; # 서버 도메인 이름
root /var/www/html; # 웹 콘텐츠가 위치하는 루트 디렉토리
index index.html; # 기본 인덱스 파일
location / {
try_files $uri $uri/ =404; # 요청된 파일이 존재하지 않으면 404 반환
}
}
로드밸런싱 설정 예시
http {
upstream backend_servers {
server backend1.example.com weight=5; # 백엔드 서버 1
server backend2.example.com weight=1; # 백엔드 서버 2
server backend3.example.com weight=1; # 백엔드 서버 3
# weight 파라미터는 서버 가중치를 설정합니다.
}
server {
listen 80; # HTTP 포트
server_name example.com; # 로드 밸런서의 도메인 이름
location / {
proxy_pass http://backend_servers; # 백엔드 서버 그룹으로 요청을 전달합니다.
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-Proto $scheme;
}
}
}
무중단배포 설정 예시
# 두 가지 업스트림 그룹 설정 (Blue와 Green)
upstream blue_backend {
server blue1.example.com; # Blue 환경 서버 1
server blue2.example.com; # Blue 환경 서버 2
}
upstream green_backend {
server green1.example.com; # Green 환경 서버 1
server green2.example.com; # Green 환경 서버 2
}
server {
listen 80;
server_name example.com;
# 배포 시 활성화된 백엔드 선택
location / {
# 현재 운영 중인 백엔드 환경을 선택 (blue 또는 green)
proxy_pass http://blue_backend; # 현재는 Blue 환경으로 요청을 전달
# proxy_pass http://green_backend; # 배포 후 Green으로 전환 가능
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-Proto $scheme;
}
}
💡위의 코드는 리버스 프록시, 로드 밸런싱, 무중단 배포의 기능이 모두 포함되어 있습니다.
🧑🏻💻 Nginx를 학습하고 이를 활용한 프로젝트 경험입니다!
https://young-code.tistory.com/11
'DevOps > Nginx' 카테고리의 다른 글
[DevOps] Nginx 삽질 일기..🥲 (0) | 2024.11.06 |
---|