그놈의 안드로이드

Nginx 아키텍처 본문

리눅스/웹 서버

Nginx 아키텍처

Sandai.Developer 2019. 1. 1. 19:22



Nginx 아키텍처 개요


기존의 동시 연결을 처리하는 프로세스 또는 스레드 기반 모델은 별도의 프로세스 또는 스레드와의 각 연결 처리와 네트워크 또는 입력 / 출력 작업에 대한 차단이 포함된다. 


응용에 따라, 메모리 및 CPU 사용 측면에서 매우 비효율적 일 수있다. 


별도의 프로세스 또는 스레드를 복제하는 작업은 힙 및 스택 메모리 할당을 포함한 새로운 런타임 환경의 준비와 새로운 실행 컨텍스트의 생성이 필요하다. 


추가적인 CPU time 역시 과도한 컨텍스트 스위치에 의한 스레드 스래싱으로 성능 저하를 유발하는 일들에 소요된다. 


이러한 복합현상들은 아파치와 같은 오래된 웹서버 아키텍처에서 실제로 나타난다. 


이것은 일반적으로 적용할 수 있는 다양한 기능의 제공과 서버 자원 사용을 최적화 하는 것 사이에서 생기는 트레이드 오프이다.






처음부터 nginx는 웹 사이트의 역동적인 성장을 가능하게 하면서 보다 좋은 성능, 밀도, 서버 자원의 경제적인 사용을 달성하기 위한 전용도구로 의도되어 다른 모델을 따랐다. 


그것은 실제로 다양한 운영 체제에서 향상된 이벤트 기반 메커니즘의 지속적인 개발에 의해 영향을 받았다. 


그 결과로 모듈식, 이벤트-드리븐, 비동기, 싱글-스레디드, 논-블러킹 아키텍처가 되었고, 이것은 nginx 코드의 기본이 되었다.






nginx는 다중화 및 이벤트 알림을 중점적으로 사용하고, 별도의 프로세스를 분리하기 위하여 특별한 작업을 할당한다. 


연결은 worker라 불리는 한정된 싱글-스레디드 프로세스의 매우 효율적인 실행 루프에서 처리된다. 


각 workernginx는 초당 수천개의 동시 연결과 요청을 처리할 수 있다.







Nginx 코드구조


nginx worker 코드는 코어 및 기능 모듈을 포함한다. 


nginx의 핵심은 요청 처리의 각 단계에서 모듈의 코드의 해당 부분을 실행하고 타이트 한 실행-루프를 유지하도록 만들어졌다. 


모듈들은 대부분 프리젠테이션과 응용 프로그램 레이어 기능으로 구성된다. 


모듈들은 프록싱이 활성화 될 때 요청을 업스트림 서버(back-end server)에 전달하고, 서버-사이드 작업을 적용하고, 아웃 바운드 필터링을 수행하고, 컨텐츠를 변환하고, 네트워크 및 스토리지에서 읽거나 저장한다.



nginx의 모듈형 아키텍처는 일반적으로 개발자가 nginx 코어를 수정하지 않고 웹 서버 기능들을 확장할 수 있게 한다. 


nginx 모듈은 핵심 모듈, 이벤트 모듈, phase 핸들러, 프로토콜, 변수 핸들러, 필터, 업스트림 및 로드 밸런서와 같이 조금씩 다른 기능을 가진다. 


이 때, nginx를 동적으로 로드된 모듈을 지원하지 않는다. 


즉, 모듈들은 빌드 단계에서 핵심모듈과 함께 컴파일된다. 


그러나,로드 가능한 모듈 및 ABI에 대한 지원은 향후 주요 릴리스에서 지원될 예정이다. 


다른 모듈들의 기능에 대한 상세정보는 14.4 절에서 찾을 수 있다.



네트웍 연결 및 컨텐츠 처리를 위한 접수, 처리 및 관리와 같은 다양한 작업을 처리하는 동안, nginx는 리눅스, Solaris 및 BSD 기반 운영 체제에서 이벤트 알림 메커니즘과 kqueue, epoll, 이벤트 포트들과 같은 약간의 디스크 I/O 성능 향상 기법을 사용한다. 


목표는 OS에 가능한 많은 힌트를 제공하여 인바운드 및 아웃바운드, 디스크 처리, 소켓 read/write, 타임아웃 등에 대한 응답을 적시에 비동기식으로 받기 위한 것이다. 


멀티플렉싱 및 향상된 I/O 처리를 위한 다른 방법은 최적화 된 유닉스 기반의 OS에서 nginx를 구동하는 것이다.



Image of 1640 article




Nginx 워커모델


이전에 언급했듯이, nginx는 모든 연결을 위하여 프로세스나 스레드를 복제하지 않는다. 


대신, 워커 프로세스들은 listen 소켓으로부터 새로운 요청을 받고, 워커 당 수천 개의 연결을 처리하기 위해 각 워커 내부의 매우 효율적인 실행-루프를 수행한다. 


nginx에는 각 워커들에게 커넥션을 전달하거나 분배하는 기능은 없다. 


이것은 OS 커널 기능으로 이루어진다. 


nginx가 기동될 때 listen 소켓의 초기 세트가 만들어지면, 워커는 HTTP 요청과 응답을 처리하는 동안 계속해서 소켓에서 접수하고, 읽고, 쓰기를 반복한다.



실행-루프는 nginx 워커 코드의 가장 복잡한 부분이다. 


종합적인 내부 호출을 포함하고 있으며 비동기 작업 처리의 아이디어에 크게 의존적이다. 


비동기 작업은 모듈성, 이벤트 알림, 콜백 함수의 광범위한 사용과 잘 조정된 타이머를 통해 구현된다. 


전반적으로, 핵심 원칙은 논-블로킹(non-blocking)이 될 것이다. 


nginx가 block 되는 유일한 상황은 워커 프로세스를 위한 디스크 스토리지 성능이 충분하지 않을 때일 것이다.



왜냐하면, nginx는 각 커넥션마다 프로세스나 스레드를 fork 시키지 않으며, 메모리 사용은 대부분의 경우에 매우 적게 그리고 효율적이기 때문이다.


nginx는 프로세스나 스레드에 대한 지속적인 생성-파괴 패턴이 없기 때문에 CPU 사이클을 절약한다. 


nginx가 하는 일은 네트워크와 스토리지의 상태를 확인하고, 새로운 연결을 초기화 하고, 실행 루프에 추가하고, 연결이 완료되어 실행-루프에서 할당해제 및 제거될 때까지 비동기식으로 처리를 한다. 


syscall의 조심스러운 사용 및 pool과 slab 메모리 할당과 같은 인터페이스를 지원하기 위한 정교한 구현과 결합할 때, nginx는 극한의 부하상황에서도 비교적 낮은 CPU 사용량을 유지할 수 있다.



그 이유는 nginx가 커넥션들을 관리하기 위하여 몇 개의 worker들만 생성하기 때문에, multiple core에서 잘 조정된다. 


일반적으로, 코어 당 한개의 separateworker는 멀티 코어 아키텍처의 전체 사용을 허용하고, 스레드 스레싱과 락을 방지한다. 


자원 고갈은 없고, 자원 조절 메카니즘은 single-threaded worker process 내에서 격리된다. 


또한이 모델은 물리적 저장 장치에 걸쳐 더 많은 확장성을 제공하고, 더 많은 디스크 활용을 용이하게 하고, 디스크 I/O 차단을 방지할 수 있다. 


결과적으로, 서버 자원은 일부의 workers 간에 부하는 분산하게 되어 보다 효율적으로 이용된다.



nginx의 workers 수는 디스크 사용 및 CPU 부하 패턴을 참고하여 조정해야 한다. 


여기 몇몇의 기본적인 규칙들이 있는데, 시스템 관리자는 부하량에 따라 몇 가지의 구성을 시도해야 한다. 


일반적인 권장사항은 다음과 같다. 


부하패턴이 CPU 위주이면 - 예를 들면, 많은 양은 TCP/IP를 관리하거나, SSL 또는 압축작업 - nginx의 workers 수는 CPU 코어 수에 맞추어야 하고, 부하패턴이 디스크 I/O 위주이면 - 스토리지에서 여러 종류의 컨텐츠를 서비스 하거나, 프록시 기능 - workers 수는 CPU 코어 수의 1.5배 ~ 2배 정도로 맞추면 된다. 


이 접근법의 효율은 디스크 스토리지의 종류 및 구성에 달려 있지만. 일부 엔지니어는 개별 스토리지 유닛의 수에 기반하여 workers 수를 결정한다.



nginx의 개발자가 차기 버전에서 해결하게 될 하나의 큰 문제는 디스크 I/O에서 발생하는 많은 blocking들을 방지하는 방법이다. 


특정 worker에 의해 생성된 디스크 작업을 제공하기에 스토리지 성능이 충분하지 않다면, thatworker는 여전히 디스크에서 읽기/쓰기를 할 때 block 될 것이다. 


일련의 메커니즘과 구성 파일은 이와 같은 디스크 I/O 병목 시나리오를 완화하기 위해 존재한다. 


특히, sendfile 이나 AIO(AsyncI/O) 같은 옵션의 조합은 일반적으로 디스크 성능을 위하여 많은 도움이 된다. 


nginx 설치는 데이터 세트, nginx가 사용할 수 있는 메모리의 양 및 스토리지 아키텍처를 기반으로 계획되어야 한다.



기존 worker 모델의 또 다른 문제는 임베디드 스크립트에 대한 제한적인 지원과 관련이 있다. 


표준 nginx 배포판 자체는 내장 Perl 스크립트만 지원된다. 


이에 대한 간단한 설명이 있다. 


중요한 문제는 예상외로 어떤 조작이나 종료 시에 block 되는 임베디드 스크립트의 가능성이다.


이런 유형의 동작은 worker가 한번에 수천 개의 연결에 영향을 미치는 hang 상태에 빠질 수 있다. 


다양한 영역의 응용을 위해서 더 쉽게​​, 보다 안정적으로 사용할 수 있도록 nginx에 내장된 스크립트를 만들기 위한 작업이 계획되어 있다.




'리눅스 > 웹 서버' 카테고리의 다른 글

Apache Prefork, Worker, Event  (0) 2019.01.01
WAS (Web Application Server) 란?  (0) 2019.01.01
Lighttpd error code 500  (0) 2018.12.31
Tornado 웹서버 구성  (0) 2018.12.30
Vert.x 웹서버 구성  (0) 2018.12.30
Comments