프로그래밍/Infra

[nginx] (1) nginx 그리고 기본 역할

Churnobyl 2024. 6. 26. 10:40
728x90
반응형

nginx


1. What is nginx?

 nginx(발음: engine-x)는 경량 웹 서버로 이고르 시쇼브(이하 이고르)가 직장에서 사용하던 웹서버인 Apache HTTPd의 문제점을 해결하기 위해 2004년 처음 개발했다. 이 문제는 C10K Problem라는 별명으로 알려져 있는데, 10,000개의 클라이언트의 동시 연결을 단일 서버에서 처리할 시 하드웨어의 성능이 충분함에도 불구하고 당시 Apache HTTPd의 작동 방식으로 인해 성능이 저하되는 문제였다. 물론 C10K라는 이름은 Apache HTTPd에만 한정된 용어가 아니고, 그 시절 세계에서 가장 큰 서버가 처리하는 한계가 1만명 정도였기 때문에 이러한 이름이 붙었다.

 

 상황을 간략하게 설명하면, 초기 Apache HTTPd클라이언트로부터 요청을 받으면 요청을 처리하기 위한 프로세스나 쓰레드를 새로 만들고 소켓(Socket)을 열어 통신하는 구조였다. 이는 전통적이고 기본적인 통신 기법이었고 당시 그 시대엔 접속량이 많지 않았기 때문에 크게 문제가 되지 않았다. 하지만 세상이 점차 발전함에 따라 인터넷 세상은 더 활발해지고 동시에 특정 서버에 접속하려는 클라이언트의 수가 크게 늘어났다.

 

당시 Apache HTTPd의 요청 처리 방식

 

 앞서 말한 것처럼 당시 Apache HTTPd의 작동 방식은 클라이언트가 접속 요청을 할 때마다 새로운 프로세스나 쓰레드를 생성하는 것이다. 그리고 우리가 알다시피 이러한 운영은 CPU와 메모리 자원의 낭비가 크다. thread() 명령을 통해 새로운 쓰레드를 생성할 때마다 각 쓰레드는 별도의 메모리 스택을 가지므로 한 개의 쓰레드가 1MB만 차지한다고 해도 10,000명의 요청을 동시에 처리하기 위해서는 최소 10GB의 메모리가 필요하다. 만약 돈을 빵빵하게 써서 메모리가 넉넉해, 1만개의 쓰레드를 생성해도 문제가 전혀 없다고 하더라도, 이제는 경합 조건(Racing Condition)문제가 대두된다. 한정된 CPU 자원을 차지하기 위한 경쟁에 1만개의 쓰레드가 참여한다면 정신이 나가버릴 것이다.

 

nginx의 Event-Driven 방식 아키텍쳐

 

 이고르는 이 문제를 해결하기 위해 유닉스와 기타 고전적인 분산 시스템의 설계에 영감을 받아 Event-Driven방식의 아키텍쳐를 개발했고 이것이 바로 nginx다. nginx가 해결한 방식은 위의 그림과 같다.

 

 nginx의 가장 큰 특징은 Master Process-Worker Process방식으로, Master Process구성 파일을 읽고 포트를 바인딩하는 등의 권한이 필요한 작업을 수행하고 구성 파일이 지정한 수의 Worker Process를 생성한다. 그리고 실제로 일을 하는 친구들이 바로 Worker Process다.

 

 Worker Process는 생성될 때 Master Process로부터 Listen Socket 세트를 함께 제공 받는다. Worker Process 왼쪽의 귀 모양이 Listen Socket이며, 커널로부터 이벤트를 기다린다. nginx는 여러 Worker Process로 부하를 분산하기 위해 커널 특히, Unix 계열 OS 커널의 SO_REUSERPORT 옵션을 사용하는데, 이 옵션을 이용한 nginx에서 Socket Sharding라고 부르는 이 기술은 같은 포트로 들어오는 워크로드를 여러 프로세스로 분산시킬 수 있다. 리눅스 커널의 도움을 받아 클라이언트로부터 들어오는 요청이 여러 Worker Process로 분산돼 들어오면 Worker Process의 Listen Socket은 각 클라이언트의 요청마다 Connection Socket을 만든다. Connection Socket은 각각 Non-blocking I/O 방식으로 해당 클라이언트로부터 요청을 기다리고 Worker Process는 수많은 Connection Socket 중에서 요청이 온 클라이언트만 처리하면 된다. 따라서 특정 클라이언트의 요청이 올 때까지 기다릴 필요가 없다.

 

 Connection Socket들은 추가될 때마다 소량의 추가 메모리를 사용하므로 당시 HTTPd의 방식보다 리소스 측면에서도 유리하다. 물론 지금은 Apache 제품도 많이 발전해서 프로젝트의 성향에 따라 사용하면 된다고 한다.

 

하지만

 

출처 W3Techs.com

 

 nginx의 점유율이 계속해서 증가하더니 2023년에는 Apache를 제치고 1위를 달성했다고 한다. 앞으로도 이러한 추세는 계속될 듯하다.

 


2. nginx의 역할

nginx의 다양한 역할

 

 nginx는 수많은 클라이언트와 서버의 연결을 원활하게 하는 역할 뿐만 아니라 추가적인 개발을 통해 서버단의 최전방에서 더 많은 역할을 수행한다. 위의 그림의 Usage를 요약하면 다음과 같다.

  • Usage1 : 포트 포워딩
  • Usage2 : 로드 밸런싱
  • Usage3 : 캐싱
  • Usage4 : 정적 리소스 제공

 그럼 각각의 역할에 대해서 알아보자.

 


포트 포워딩

라우터의 포트 포워딩

 

 일반적으로 포트 포워딩은 컴퓨터 네트워크에서 패킷이 라우터나 방화벽 같은 네트워크 게이트웨이를 통과하는 동안 네트워크 주소를 변환해 트래픽을 리디렉션하는 것을 의미한다. 즉 OSI 7계층 모델에서 세번째 계층인 네트워크 계층(Layer 3)에서 사용된다. 그리고 이러한 포트 포워딩은 외부 네트워크의  사용자가 개인 네트워크의 서비스에 액세스할 수 있도록 하는 데 사용된다.

 

 nginx의 포트 포워딩은 라우터의 포트 포워딩과 다르게 애플리케이션 계층(Layer 7)에서 일반적으로 HTTP, HTTPS, Mail, Stream (TCP), uWSGI 등 상위 수준 프로토콜을 관리하는데 사용된다. nginx는 서버단에서 역방향 프록시 역할을 하며 들어오는 포트에 따라 다른 애플리케이션으로 라우팅시킨다.

 

 


로드 밸런싱

 nginx는 아주 간단한 설정만으로도 로드 밸런싱을 시킬 수 있다. 특별한 설정이 없는 경우 라운드 로빈 방식으로 부하가 분산되며 두 가지 옵션을 추가적으로 제공한다. 그리고 weight 옵션을 이용해 각 서버에 분산을 어떻게 할 것인지 지정할 수도 있으며, 주 서버가 모두 다운됐을 경우 backup서버로 트래픽을 이동시킬 수도 있다.

 


캐싱

 nginx는 콘텐츠 캐시를 가지고 있으며, 클라이언트와 Web Application Server 사이에 위치해 보이는 모든 콘텐츠의 복사본을 저장한다. 만약 클라이언트가 캐시에 저장된 컨텐츠를 요청하면 Web Application Server와 통신하는 대신 직접 복사본을 반환한다. nginx가 서버단의 최전방에 있기 때문에 성능 향상에 큰 도움이 될 수 있다.

 

 


정적 리소스 제공

 nginx는 서버에 있는 정적 리소스를 제공해줄 수 있다. 현재 대부분의 백엔드 서버는 json을 통해 동적 데이터를 주고 받는 RESTful한 방식이라 현재는 크게 쓸 일은 없을 것 같다.

 

 만약 잘못된 경로로 접근했을 때 

 

nginx 502 Bad Gateway

 

이러한 화면 대신 특정한 html파일을 제공해줄 수도 있지 않을까 싶다.

 

반응형

'프로그래밍 > Infra' 카테고리의 다른 글

[nginx] (2) nginx.conf  (0) 2024.06.30
[AWS] Amazon Web Services - (4) Amazon VPC  (0) 2023.05.04
[AWS] Amazon Web Services - (3) EC2  (0) 2023.05.03
[AWS] Amazon Web Services - (2) IAM  (0) 2023.05.02
[AWS] Amazon Web Service - (1) AWS란?  (0) 2023.05.01