0. 서론
최근 프로젝트에서 proxy서버를 만들면서 Nginx라는 웹 서버를 사용하게 되었다.
웹 서버에 대해서는 Apache에 대해서만 알고 있었는데, 최근에는 Apache보다 더 많이 사용된다고 한다.
이번에는 nginx에 대해서 더 알아보기 위해서 분석해보고자 했는데, Youtube영상 중 피케이님이 Nginx에 대해서 정리를 해주신 영상을 토대로 내용을 정리해보고자 한다.
우아한 테크 - 피케이의 Nginx [https://www.youtube.com/watch?v=6FAwAXXj5N0]
1. Nginx이전의 시대
1995년 당시, unix기반으로 만들어진 NCSA HTTPd라는 최초의 웹서버가 존재했었다. 하지만, 버그가 많아서 개발자들이 사용하기 힘들었다. 이를 개선하기 위해 뛰어난 개발자들이 발벗고 나서서 버그를 수정하고, 구조를 변경하고, 기능을 추가한 것이 Apache 서버이다.
Apache서버는 요청이 들어오면 connection을 형성하기위해 precess를 생성한다. 그래서 요청이 들어올 때마다 process를 만든다. 여기서 프로세스를 만드는데 시간이 오래 걸리다보다 미리 프로세스를 만들어 놓는 PREFORK 방식을 사용했다.그래서 새로운 클라이언트로부터 요청이 들어오면, 미리 만든 프로세스를 할당했다. 만들어 놓은 프로세스가 모두 할당되었다면 새로 프로세스를 만들었다.
이런 구조는 개발하기 쉬워져서, 다양한 모듈을 만들어서 기능을 추가하기 좋았다. 이런식으로 Apache는 동적 컨텐츠를 처리할 수 있게 되었다. 확장성이 좋다는 이유로 요청을 받고 응답을 처리하는 과정을 하나의 서버에서 처리하기 좋았다.
1996년 아파치 웹 서버는 나온지 1년이 된 해에 전세계 웹서버 점유율 1등을 차지하게 되었다.
C10K(Connection 10000 Problem)
1999년 인터넷 트래픽이 점점 늘어나기 시작되었다.
컴퓨터의 많은 보급과 많은 요청에 따라 서버에 동시에 연결된 connection이 많아졌을 때, 더이상 connection을 형성하지 못하는 문제가 생기기 시작했다. 이를 C10K(Connection 10000 Problem)라는 문제라고 칭했다. 클라이언트 수가 많아지면서, 동시 connection이 점점 많아지고, 10000단위가 넘어가는 순간 서버는 connection을 형성하지 못하게 되었다.
"동시에 연결된 커넥션 수"라는 의미는, 요청을 처리하기위해 서버가 한 시점에 얼마나 많은 클라이언트들과 connection을 형성하고 있는지에 대한 지표이다. connection을 형성하는데, 여러 절차가 있기 때문에 오래 유지되었다. 그래서 매번 이렇게 요청마다 connection을 만드는 것은 비효율적이었다.
이 때문에, 요청을 보낼 때 만들어진 connection이 있다면 재활용하자는 생각을 했다.http프로토콜중에 Keep-Alive라는 헤더가 있다. 이 헤더에 적힌 시간만큼 클라이언트와 서버는 한번 연결된 connection을 유지한다.
하드웨어는 발전속도가 빨라서 문제가 없었지만 문제는 apache서버의 구조였다. apache는 connection마다 프로세스를 할당하므로 동시에 처리하는 connection이 많으면 동시에 처리하는 프로세스가 많아지고, 메모리 부족현상을 만들었다.
apache의 여러 기능을 추가하는 특징은 프로세스가 차지하는 리소스의 양을 늘리고, 많은 connection에서 요청이 들어오기 시작하면 cpu 코어는 매번 프로세스를 바꿔가며 일을 했다. 한마디로 CPU가 감당해야할 일이 너무 많았다.
http://www.kegel.com/c10k.html
2. Nginx의 등장
이러한 이유들로, Apache측은 구조를 완벽히 바꾸지는 못하지만 꾸준히 개선을 하고 있었다.
2004년, apache server를 보완하고 새로운 구조를 채택한 소프트웨어가 나왔다. 이것이 Nginx이다.
초기의 Nginx는 Apache와 같이 사용하기 위해서 만들어졌다. apache 서버의 구조적 한계를 nginx로 해결하고자 했다. apache서버 앞단에 nginx를 둬서 apache가 감당했던 동시 connection을 nginx가 유지해서 apache의 부하를 줄일 수 있었다. 또한 nginx는 자체로 웹서버라 정적파일을 처리할 수 있었다. 동적파일이 들어왔을 때만 apache와 connection을 유지했다.
https://www.nginx.com/category/opinion/
nginx는 어떻게 많은 양의 동시 connection을 처리할 수 있었을까?
요점은 "만들어진 프로세스 수"에 있다. nginx에는 master process가 존재하는데, master process는 설정파일을 읽고, 그에 따라 worker process(실질적으로 일하는 process)를 만들고, 만들어질 때 각자 지정된 소켓을 배정받는다. 이 소켓에 새로운 클라이언트로부터 요청이 들어오면, connection을 형성하고 처리한다. connection은 Keep-alive동안 유지된다.
worker process는 한개만 담당하지 않는다. 아무런 요청이 없으면 새로운 connection를 형성하거나 만들어진 다른 connection으로부터 요청을 처리한다. 이러한 처리과정을 이벤트라고 칭하는데, os커널이 큐형태로 worker process로 전달되는데, 이 이벤트는 큐에담긴 상태로 worker process가 처리할 때까지 비동기방식으로 대기한다. worker precess는 하나의 스레드로 이벤트를 꺼내서 처리해나간다. 이렇게 하면, 쉬지않고 계속 일을 할 수 있는 장점이 있다. apache의 요청이 없으면 놀고 있는 process보다 효율적이다.
만약 요청중 하나가 오래걸리는 작업이라면, 뒤에 있는 이벤트는 계속 blocking될 것이다. nginx는 이런상황을 방지하기 위해 오래 걸리는 작업을 위해 별도의 thread pool을 만든다. worker process는 오래걸릴 것 같으면 thread pool에게 위임하고 다른 이벤트를 처리하러 간다. worker process는 cpu코어 갯수만큼 생성된다. 이렇게 하면, 코어가 담당하는 프로세스를 바꾸는 횟수를 줄일 수 있고, cpu의 부하가 줄어든다.
장점과 단점
단점으로는 "기능을 추가하기위해 현재 돌아가는 worker process를 종료한다면??" 해당 worker가 관리하는 connection을 처리하지 못한다. 그래서 nginx는 개발자가 직접 모듈을 만들기 어려운 점이 있다.
그에 반해 장점이 수 많은 동시 커넥션을 처리하고,프로세스를 적게 만들어 가볍고, nginx설정을 동적으로 바꾸는 것을 가능하게 했다. 개발자가 설정파일을 변경하고 nginx에 해당 설정을 적용하면, master process는 그 설정에 맞는 worker process를 따로 생성한다. 기존에 있는 worker process가 connection을 더이상 형성하지 못하게 한다. 시간이 지나 기존 worker process가 담당 이벤트처리가 끝나면 해당 프로세스를 처리한다.
이러한 동적 설정 변경은 어디에 쓰일까? 여러 동시 connection을 nginx가 관리하다가 뒷단에 서버가 추가되는 상황이 생겼다고 해보자. 이 때, nginx가 "로드밸런서 역할"(요청을 여러 서버로 분산)을 하게 된다.
"nginx는 수많은 conneciton을 맡고 있기 때문에, 뒷단에 서버 추가를 위해 설정파일 변경을 위해 nginx를 종료해야 하는가??" 아니다. 동적으로 설정을 변경하면 동시 connection을 유지한 채 서버를 추가할 수 있다. nginx는 설정변경을 초당 수십번을 해도 무리없이 conneciton 관리가 가능하다. 이벤트 기반의 구조라 가능한 방법이다.
nginx가 처음 출시되었을 때는 아직 apache가 1등이었다. 2008년부터 nginx가 치고올라가기 시작했다. 왜냐하면, 2008년에는 아이폰 덕분에 스마트폰 시장이 인터넷 환경을 바꾸기 시작했다. 사람들이 인터넷을 더 많이 사용하게 되는 계기이자, 동시 connection이 폭발적으로 증가하기 시작했다. 다양한 정보를 실시간으로 제공받고 싶어졌다. 그래서 브라우저도 리소스를 빠르게 가져오기 위해 여러 tcp-connection을 형성하고 keep-alive로 유지되었다. 동시 connection을 처리할 회사가 점점 많아지고 회사들은 nginx에 눈을 돌리기 시작했다. 이 때문에 nginx는 인터넷 트래픽에 관여하는 비율이 점점 증가한다.
https://aosabook.org/en/v2/nginx.html
3. Apache와 Nginx의 차이
apache도 이후에 MPMs(Multi processing module)라는 모듈을 추가해서 성능을 제공했는데, apache를 어떻게 쓸지 선택할 수 있게 해주는 모듈이었다. 안정성을 위해 기존의 PROFORK방식을, 성능향상을 위해서라면 WORKERS라는 스레드를 만들어서 요청을 처리하도록 했다.
성능테스트 결과 동시 connection 관련 지표에서는 nginx가 apache를 앞선다. nginx는 동시 connection이 많아져도 메모리 사용량이 적은 한편, apache는 많이 사용한다. 이는 nginx의 conenction 관리가 얼마나 잘 되고 있는지를 보여준다.
apache 서버 이전의 웹 서버는 버그가 매우 많았다. 이러한 경험들을 겪으며, apache 서버는 여러 OS에 안정적이라는 장점이 있다. 반면 nginx는 windows에서는 제대로된 성능을 발현하지 못한다. apache는 확장성이 좋아 모듈 추가로 기능 추가가 편해서 수많은 기능 추가가 가능하다. 이러한 이유로 현재 사용하는 apache가 잘돌아가면 굳이 바꿀 필요성을 못느낀다.
여기서 서버의 선택할 수 있는 기준을 알 수 있다. 만들어진 목적 자체가 다르기 때문이다. Apache는 안정성, 확장성이 중요했고, nginx는 connection문제가 중요했기 때문이다.
4. 2021년 이후의 nginx 사용
앞서 nginx는 웹 서버, 로드밸런서의 역할을 했는데, nginx는 동시 connection을 유지할 수 있고, 가볍다는 특징으로 다양한 방법으로 웹 서버 가속기 역할을 한다. SSL 터미네이션을 수행할 수 있는데, SSL 터미네이션은 nginx가 client와는 https통신을 하고 서버와는 http통신을 하도록 한다. 이 구조를 만들어서 서버가 복호화 과정을 하지않아도 되서 서버의 비즈니스 로직 리소스를 줄여준다.
nginx는 http프로토콜을 사용해서 전달하는 컨텐츠를 캐싱을 할 수 있다. 캐싱을 하는 경우에는 client와 가깝게 배치해서 서버로 받은 응답을 복원하고 client에 전달한다.
이외에도 HSTS(HTTP Strict Transport Security), CORS 처리, TCP/UDP 커넥션 부하 분산, HTTP/2 등등의 많은 방식으로 서버를 지원한다.
'Backend > 개념,공부' 카테고리의 다른 글
OOP란 대체 무엇일까?? (1) | 2023.12.31 |
---|---|
Redis? (0) | 2023.12.08 |
데이터베이스 - 데이터베이스(DB), MariaDB (0) | 2023.06.18 |