[Nginx] 내부 구조와 리버스 프록시
엔진엑스는 정적 리소스를 제공하는 웹 서버로도 동작할 수 있고 여러 백엔드 서버로 로드밸런싱을 수행하는 리버스 프록시, 메일 프록시로도 동작할 수 있는 다재다능한 웹 서버이다.
리액트로 프론트엔드 웹 애플리케이션을 만들고 사용자들에게 배포 할 때 엔진엑스 웹 서버를 사용할 수 있다.
npm build 명령어로 애플리케이션을 번들링하고 엔진엑스를 정적 리소스를 제공하는 웹 서버로 사용하는데, 이 때 root 지시어를 사용해 번들링된 파일이 위치한 디렉토리를 지정하고 모든 서버 요청을 index.html으로 리다이렉트하도록 설정해 SPA 라우팅을 처리한다.
server {
listen 80;
server_name myapp.com;
root /app/react/build;
index index.html;
location / {
try_files $uri /index.html;
}
}
location / : 서버에 들어오는 모든 요청을 처리한다.
try_files $uri /index.html : 요청된 uri가 실제로 서버에 있는 파일이나 디렉토리와 일치하는지 확인한다.
이런 식으로 엔진엑스 설정 파일을 구성하면, 프론트엔드 웹 애플리케이션을 서빙할 수 있다.
엔진엑스를 리버스 프록시로 사용하는 경우, 클라이언트는 엔진엑스에게 요청을 보내고 엔진엑스는 여러 웹 서버의 상태를 확인하고 적절한 웹 서버에게 요청을 전달하는 로드밸런서 역할을 수행한다.
엔진엑스의 주요 기능은 OSI 7계층 중 4계층과 7계층에 집중된다.
Layer 4
TCP/IP 스택만 확인할 수 있어, 소스IP / 소스PORT / 목적지IP / 목적지PORT 를 확인할 수 있다.
이 부분에서 엔진엑스가 개입해 목적지를 조작하고 적절한 백엔드 서버로 요청을 넘겨주는 방식으로 사용한다.
데이터베이스 서버, DNS 서버에 대한 로드밸런싱을 수행할 수 있다.
Layer 7
실제 애플리케이션과 프로토콜을 확인할 수 있는 계층으로 HTTP 트래픽을 여러 웹 서버로 분산시키는 로드 밸런서로 동작할 수 있다.
동적 웹 컨텐츠를 처리하고 제공하는 웹 서버로도 동작할 수 있고, 캐시 / SSL, TLS 암호화 / DDoS 공격 방어 등 다양한 기능을 제공한다.
HTTP 트래픽에 초점을 맞춰 HTTP 헤더, 쿠키 등 애플리케이션 계층의 데이터를 기반으로 트래픽을 분산시키고 세션을 관리할 수 있어 REST API 서버에서 주로 사용된다.
기본적으로 들어오는 요청을 순서대로 각 서버에 할당하는 라운드 로빈 알고리즘을 사용해 로드 밸런싱을 처리하는데..
엔진엑스 설정파일의 upstream 지시어로 로드밸런싱 알고리즘을 설정할 수 있다.
http {
upstream myapp {
server example1.com weight=3;
server example2.com weight=2;
server example3.com;
}
server {
location / {
proxy_pass http://myapp;
}
}
}
예시는 각 서버에 가중치를 할당해서 가중치가 높은 서버에 더 많은 요청을 할당하는 가중 라운드 로빈 알고리즘을 사용한다.
각 서버의 구성과 아키텍처에 따라 적절한 알고리즘을 사용하자.
프록시는 클라이언트와 서버 사이에서 중계 역할을 하는 서버를 의미하고, 클라이언트의 실제 ip를 숨기고 캐싱, 접근 제어 등 기능을 수행한다.
리버스 프록시도 클라이언트의 요청을 서버에게 전달하는건 같지만 클라이언트는 리버스 프록시와 직접 통신하고 리버스 프록시는 들어오는 요청을 여러 서버에 균등하게 분산시킨다.
프록시는 클라이언트 측에 위치해서 중계 역할을, 리버스 프록시는 서버 측에 위치해서 요청을 분산시킨다.
클라이언트가 엔진엑스 리버스 프록시에 요청할 때는 암호화를 위해 TLS/SSL을 적용하는데...
이 부분에서 엔진엑스가 암호화를 처리하는 방법으로는 두 가지가 있다.
TLS Termination
엔진엑스에서 TLS 암호화를 해제한다.
클라이언트는 엔진엑스에게 암호화된 HTTPS 트래픽을 주고, 엔진엑스는 이 암호화를 해제한 후 HTTP 프로토콜을 사용해 내부 네트워크의 서버로 전달한다.
내부 네트워크는 웬만하면 안전하니.. 굳이 암호화 하지 않는 전략이다.
서버가 엔진엑스와 다른 호스트에서 배포돼 내부 네트워크를 사용할 수 없는 경우 TLS Termination과 TLS re-encryption을 사용한다.
HTTPS로 전달된 트래픽을 엔진엑스가 해제하고, 다시 암호화 한 후 각 서버에게 전달하는 방식인데.. 암호화를 해제해서 얻을 수 있는 이득이 없는 경우 TLS Passthrough 방식을 사용하는 편이 더 효과적이다.
복호화해서 WAF 방화벽을 사용하거나, 정적 컨텐츠를 캐싱하거나, 스티키 세션을 구현하는 등 특별한 목적이 없다면 TLS Passthrough를 사용하는 편이 합리적이다.
TLS Passthrough
클라이언트로부터 받은 HTTPS 암호화를 해제하지 않고 다른 서버로 전달하는 방식이다.
TLS 핸드셰이크를 시작하지 않고 SNI 확장으로 연결의 목적지 서버를 식별한다.
내부 서버에서 직접 암호화를 해제하니 엔진엑스가 암호화 키를 가질 필요가 없어 좀 더 안전하다.
엔진엑스의 내부는 마스터 - 워커 아키텍처를 사용한다.
마스터 프로세스는 nginx.conf 파일을 읽고 워커 프로세스를 관리하고, 실제 네트워크 요청은 워커 프로세스가 처리한다.
워커 프로세스는 CPU코어에 분산될 수 있고 사용 가능한 CPU 코어 수에 따라 워커 수를 설정한다.
각 워커들은 이벤트 루프 내에서 비동기로 동작해 블로킹 작업 없이 연결을 처리할 수 있다.
클라이언트가 Nginx에게 TCP 연결을 요청하면, Nginx는 마스터 프로세스가 생성한 리스닝 소켓을 통해 클라이언트의 요청을 수락한다.
워커 프로세스 중 하나가 연결을 수락하면 nginx.conf 에 정의된 규칙에 따라 해당 워커는 클라이언트의 요청을 처리해준다. (정적 파일 제공, 프록시 기능 등..)
Nginx는 각 워커가 하나의 CPU 코어에만 바인딩되도록 설정하는 CPU affinity를 지원해 컨텍스트 스위칭을 최소화하는데..
따라서 워커 프로세스의 수는 nginx.conf 의 worker_processes 지시어로 설정할 수 있지만 서버의 CPU 코어 수와 일치시키는게 좋다.
이런 아키텍처와 비동기, 이벤트 기반 처리 방식으로 엔진엑스는 효율적으로 대규모 트래픽을 관리한다.
'Computer Science > Network' 카테고리의 다른 글
[Nginx] Timeout (0) | 2023.12.24 |
---|---|
[Network] 백엔드 아키텍처 (0) | 2023.12.21 |
[HTTP] HTTP 쿠키와 세션 (0) | 2023.06.12 |
[HTTP] 헤더 / 쿠키와 캐시 (0) | 2022.08.13 |
[HTTP] 상태코드 (2) | 2022.08.12 |
댓글
이 글 공유하기
다른 글
-
[Nginx] Timeout
[Nginx] Timeout
2023.12.24 -
[Network] 백엔드 아키텍처
[Network] 백엔드 아키텍처
2023.12.21 -
[HTTP] HTTP 쿠키와 세션
[HTTP] HTTP 쿠키와 세션
2023.06.12 -
[HTTP] 헤더 / 쿠키와 캐시
[HTTP] 헤더 / 쿠키와 캐시
2022.08.13