caffeine-library / system-design-interview

🌱 가상 면접 사례로 배우는 대규모 시스템 설계 기초를 읽는 스터디
4 stars 0 forks source link

[additional] Apache vs Nginx #3

Open wooyounggggg opened 2 years ago

wooyounggggg commented 2 years ago

연관 챕터

1

조사 내용

Apache vs Nginx

Apache와 Nginx의 역사와 동작 방식을 간략하게 살펴보면서, 어떤 상황에서 어떠한 기술이 더 적합한지 살펴봅니다.

이번주 스터디 전까지 내용을 조사 및 종합하도록 하겠습니다 😄

wooyounggggg commented 2 years ago

Apache Web Server

MPM (Multi-process Module)

Apache MPM 문서에 따르면, Apache Web Server는 사용자 요청에 의해 하나의 Connection이 생성될 때, ProcessThread를 생성하여 해당 Connection에 바인딩합니다.

이러한 MPM에는 Prefork MPM(Multi-Process 방식)Worker MPM(Multi-Process & Thread 방식) 두 가지 방식이 존재했습니다.

Prefork MPM

Prefork 방식은 위 그림과 같이, 일정 수의 프로세스를 미리 생성(Prefork)합니다. 이후, 요청의 수가 많아져 Prefork 되어있는 프로세스보다 많은 수의 요청을 받으면 새롭게 프로세스를 생성합니다. 프로세스를 할당하는 비용이 상대적으로 크기 때문에, 이러한 방식을 사용합니다. Apache의 default 설정입니다.

Worker MPM

Prefork 방식은 프로세스당 요청 하나를 처리하기 때문에, 자원 효율이 좋지 못하다는 단점이 존재합니다. 따라서 Apache Web Server는 Worker 방식을 제공합니다. Worker MPM은 위와 같이 스레드 단위로 요청을 할당하기 때문에, 동시 접속자가 많은 환경에서 Prefork 방식보다 유리하게 동작합니다.

C10k(Connection 10k) problem

1999년, 개발자 Daniel kegel은 10k개의 동시 Connection을 연결할 수 있는가라는 의미의 C10k 문제를 제기합니다.

이러한 문제 제기의 배경은, 당시의 Unix의 Socket 연결이 최대 2048개, 즉 2k개에 불과했다는 기술적 한계와 더불어 인터넷이 활성화 되면서 트래픽이 기하 급수적으로 증가하는 시대적 상황이 맞물린 것에 있습니다. 당시 Unix Socket 연결 개수의 최대값이 2k로 설정되어 있을만큼, 10k의 연결은 생각하기 어려웠다는 것에 있습니다.

그러다보니, Blocking/Synchronous I/O 모델을 채택해도 문제가 없었지만, 인터넷이 활성화되면서 동시 연결이 폭증하고, 그 결과 기존 모델을 차용한 프로그램은 과다한 연결로 인한 서버 다운 등의 문제를 겪습니다.

이와 같은 C10k 문제를 해결하기 위해 개발자들은 Non-blocking/Asynchronous I/O 모델을 차용하여 문제를 해결합니다. 대표적인 사례로 Windows의 Overlapped I/O나 iocp와 같은 기술이 존재합니다.

Apache Web Server의 성능적 한계

Apache Web Server가 출현한 시점이 C10k 문제가 발생한 시점보다 더 과거였다는 것을 고려하면, Apache는 당시에 Blocking/Synchronous I/O 모델을 차용하고 있었을 것으로 추측됩니다. (현재는 비동기 통신 방식도 제공하고 있습니다.)

즉, 클라이언트 요청에 Process나 Thread를 1대1 전담 처리하는 방식이고, 이는 이전에 다루었던 Spring Webflux 이슈와 비슷한 패턴의 성능 병목을 예상할 수 있습니다.

또한, 요청마다 Thread나 Process를 계속해서 생성하기 때문에 메모리 자원 부족, Context Switching 비용 증가 등 성능적 이슈가 발생합니다.

당연히, C10k 동시 접속 문제 또한 피해갈 수 없었습니다.

wooyounggggg commented 2 years ago

Nginx

Nginx의 Blocking I/O 언급

Nginx 공식 블로그 글인 Inside NGINX: How We Designed for Performance & Scale에서는, Blocking/Sync Architecture를 채택하는 Server-Client 모델에 대해서 아래와 같이 이야기합니다.

The rather lightweight HTTP connection, represented by a file descriptor and a small amount of memory, maps to a separate thread or process, a very heavyweight operating system object. It’s a programming convenience, but it’s massively wasteful.

파일 디스크립터와 적은 양의 메모리로 표현되는 다소 가벼운 HTTP 연결은 매우 무거운 운영 체제 개체인 별도의 스레드나 프로세스에 매핑됩니다. 프로그래밍적으로 편리하지만, 자원을 굉장히 낭비하게 됩니다.