Computer Science/모델링 & 아키텍쳐 & 패턴

[CS] Apache MPM vs NGINX vs Node.js

findTheValue 2021. 7. 14. 23:58

미스터코 님의 10분 테코톡 시청 후 작성하였습니다.


간단한 정의

 

  • MPM(multi-Processing-modules)

       서버는 시스템의 네트웍 포트에 연결하고,

      요청을 받아들이며, 받아들인 요청을 처리하기 위해

      자식들에게 분배하는 다중처리 모듈(MPM)을 선택할 수있다.

  • NGINX - 웹서버
  • Node.js : Chrome V8 Javascript 엔진으로 빌드된 JavaScript 런타임.

 


[언제 어떤 것을 선택해야 하는가???????]

 세가지 모두 '웹서버'의 역할을 할 수 있다.
(Node.js는 웹서버역할도 WAS(Express.js)도 가능함. 때문에 결이 좀 다름.)

 

 

동시성은 예전이나 지금이나 중요하다.

(어느정도 기간동안 무시하지 않을 수 있는 연결들(+요청들))

-옛적엔 너무느린 네트워크(100KB 파일 응답)(0.1초 응답준비 10초 응답전송) => 높은 동시성

-요즘엔 많아진 기기(모바일, 테블릿) 연결을 유지하고 있음., 브라우저 사용 방식 변화(한 페이지로부터 여러 요청)

- 그렇다면? 혼자 처리하기 힘들면 같이 처리하면 되지 않을까??


 

[Apache MPM]


-커넥션 생성(binding, accept) -> 요청과 응답을 처리하기 위한.

-커넥션 분배

= 프로세스든 스레드든 해당 커넥션에 대한 요청을 담당합니다.

 


-모든 종류(UNIX 계열) (3가지 요청을 담당하는 방법.)-
  • prefork(프로세스)
  • worker(스레드)
  • event

 


하지만?? 10000개의 연결이 동시에 처리가 된다면??

  • 메모리 (프로세스당 1MB가 필요하다면??) -> 10GB
  • context switching(누구를 실행해야하지?)
    • 4코어면 잘해도 2500개.
    • 컨텍스트 스위칭 오버헤드 * 2500

O(n)=> n개에 비례함...

동시에 처리되어야 할 숫자에 영향을 받지 않으려면??

 

=>> O(n)에 풀던 것을 O(1)에 풀면 됨!!!

 

 


 

 

[Node.js(내부 처리 방식)]


"비동기 이벤트 주도 JavaScript런타임으로써 Node.js는 확장성 있는 네트워크 어플리케이션을 만들 수 있도록 설계 되었습니다."

  • 핵심은 이벤트 루프..(나중에 따로 공부)
  • 싱글 스레드로 돌려서 최대한 해야할 일만 할 수 있도록(JS특징 싱글스레드)
    • ex) 컨텍스트 스위칭 영향 줄이기
  • 기다려야 할 시간을 최소화(비동기 + 이벤트)

=> 네트워크 애플리케이션이 적용하기 딱 좋은 경우


동기방식

const fs = require('fs');
const data = fs.readFileSync('/file.md'); //파일을 읽을 때까지 여기서 블로킹 됩니다.
console.log(data); // morework();는 console.log이후 실행될 것 입니다.

비동기방식

const fs = require('fs');
fs.readFile('/file.md',(err,data) => {
  if (err) throw err;
  console.log(data);
});
console.log(data); // morework();는 console.log이전에 실행될 것 입니다.

=> Node.js는 하나의 흐름(ex. 함수(콜백함수))이 완전히 끝나기 전에는 다른 흐름이 실행 될 기회가 없다.

=>CPU를 많이 사용해야 되는 경우 node.js사용에 주의해야 한다.

조심해야하는 입력들

-정규표현식
-synchronous expenseve API
  -암호화
  -파일 IO
  -DNS에 요청
  -프로세스 fork
-JSON DOS

Node.js 내부처리방식 : 이벤트 루프 (이벤트를 통해 해야할 일이 큐에 등록되고 등록을 통해 제공받은 일을 실행..)

=> Node.js런타임 환경안에서 자체적으로 다음에 어떤 일을 할지 스케줄링한다.(커널에서 분배하는 개념이 x)

 

 


 

 

[NGINX]

=> 확장성에 대한 대응방식은 Node.js와 비슷하나 웹서버라는 역할에 최적화.

(좀 더 비동기 방식에 적합한 정적 입력들(CPU 점유를 적게하는))

 

[장점]

  • 빠르다
  • 로드밸런서
  • 효율성
  • 안전성
-(누가 죽어도 다른 애를 쓰면 됨!)

리버스 프록시(client로부터 server의 주소를 감추기 위한 프록시)

      //프록시는 중개인처럼 동작해 모든 HTTP트래픽을 제어

      (웹서버는 여러 보안 기능을 두고있음 앞에서 공격을 막음.)

  • 보안
  • 유연성
  • -(외부에서 직접적으로 모름!)
  • 레이턴시 감소(웹서버 역할을 해주는 애들이 다음의 역할을 해줌)-SSL(암호화): 보안에 대한 인증서(HTTPS의 보안에대한 인증)-> WAS에서 할 수 있지만 웹서버에서 해줌.
  • -캐시(웹서버의 캐싱 - 리버스 프록시의 캐싱 - 서버 단 사이의 캐싱(자주 찾을 만한 캐시를 응접실에 두고 잇음))
  • -압축(텍스트압축)

-웹페이지 접근 인증

-비동기 처리(이벤트 루프)

 

+++

=> Node.js에서 조심해야할 부분들을 많이 채워줌>

-> 웹 서버 or WAS의 서버 부담도 덜어감.

 

 

 

 

---처리 방식에 따른 비교---

 

-아파치는 다중 프로레스로 처리

(컨텍스트 스위칭)

(mpm-prefork 손님이 올때마다 프로세스를 새로 생성하는 방식)

(mpm-worker 다중 스레드로 한테이블에서 여러 가지를 처리하는 방식) - prefork보다 메모리를 덜사용함.

=> event처리방식도 추가함.

=> 다양하고 검증된 기능들을 필요로 하는곳은 신뢰도가 더 높은 아파치.(커뮤니티 파워가 더 센...)

=> tomcat을 WAS로 쓰면 mod_jk, mod_{rpxy, mod_proxy_ajp 방식을 아파치에서 자체적으로 지원해줌으로써 좀 더 효율적인 설계가 가능함.

-NGINX는 이벤트로 처리

(event driven 작은 데스크 하나만 두고 손님을 한줄로 쭉 세움.)

=> 어떤 동작을 해야하는지만 알려주고 다른 요청을 처리하는 방식(Producer Consumer Pattern과 유사)

=>CPU와 관계없이 모든 IO들을 전부 Event Listener로 미루기 때문에 흐름이 끊기지 않고 응답이 빨라

하나의 프로세스로 더 빠른 작업이 가능.(메모리적으로 리소스를 적게 처리한다는 장점)

실질적으로 3000개의 요청시 아파치가 1500의 메모리를 사용하면 NGINX는 50밖에 사용안함.

-> 컴퓨터 부담이 적음

=> 속도도 매우빠름(초당 처리할수 있는 처리가 아파치랑 비교할 바가 못됨)

=> 성능과 가벼움을 중요시 하는 서비스에는 NGINX


Node.js를 WAS로 사용하는 경우

NGINX와 apache를 포워드 프록시와 리버스 프록시로 써

리소스낭비를 막고 보안을 강화함.

(ex Node Express에서 사용하는 실제 포트를 NGINX의 80포트 Proxy서버로 숨김으로써 보안을 강화함.)

 

실질적으로 Node.js하나만 배치하면 해킹의 위험이 큼..

그러므로 혼자쓰는게 아닌 사용자가 한명이라도 있어 여러 사용자가 접속해

데이터를 생성하고 수정하는 웹 App 이라면 필히 Web server를 따로 두는게 좋음.

 

물론 최근에는 node의 보안수준이 높아져서 node만으로 서버를 운영하기 충분하다는 의견도 있으나 그럴 경우

최신버젼과 그에 맞는 보안 방법을 찾아 따로 적용하는 것을 잊지 말아야함.

 

그리고 Apache보다 NGINX를 웹서버로 두는 이유!!!는 둘다 이벤트 루프 방식을 차용하기 때문!!!!!!

=> 둘의 호환성은 Node.js창시자 라이언 달이 공언함..(버퍼 오버플로우 취약점을 NGINX를 Proxy서버로 두어 보완하라고..) (버퍼(메모리)오버플로우 : 스택(힙)에서 한계점 공간을 넘어가면 오버플로우 됏다고 함)

 

 

 

 

[적용]


1. 클라이언트가 HTTP로 접속하면 자동으로 80번 포트로 접속이 되고 HTTPS로 접속하면 443으로 접속함.

2. 80번 포트로 접속하면 NGINX가 443으로 우회(리다이렉트) 시켜줌

3. 443에서는 WAS인 Node.js의 5000으로 이어줌.

<<<Linux Ubuntu NGINX 설정>>>

sudo apt-get update
sudo apt-get update -y

sudo apt-get install nginx

sudo service nginx start

cd / etc . nginx / sites-enabled #설정파일 위치로 감
sudo rm default
sudo vi default
<<<설정파일>>>

server{
    listen 80;
    server_name idu-market.shop;

    #access_log/var/log/nginx/reverse-access.log
    #error_log/var/log/nginx/reverse-error.log

    if($host = idu-market.shop){
        return 301 https://$host$request_uri;   #HTTPS로 리다이렉트(301은 리다이렉트 시켜주는 상태코드)
    }
}

#$host는 호스트를 찾으라는 명령
<<<설정파일>>>

server{
    listen 443 ssl;  #443으로 오면 ssl인증서를 찾아라.
    server_name idu-market.shop;

    #access_log/var/log/nginx/reverse-access.log
    #error_log/var/log/nginx/reverse-error.log

    location / {
        proxy_pass http://127.0.0.1:5000;
    }
}

[결론!!]


=> 동시에 많은 연결과 요청이 있어도 성능이 그 트래픽에 영향을 받지 않도록 하기 위한 노력.

하지만 그만큼 잘 쓰기위해 노력이 많이 필요하다!(O(n)->O(1))로 바꾸기 위한!

Apache, NGINX는 각각 멀티프로세싱, 이벤트루프를 활용한 웹서버.
Node.js는 이벤트루프를 사용한 WAS.
때문에 NGINX, Node.js의 협동은 매우 강력하다!!

!!주의할 부분(connection(병목)) : 다른게 잘 되어도 병목이 될 수 있는 부분임..

혹시 내가 잘 쓰고 있는데 문제가 있다면?=> "리눅스 커널 이야기"라는 책을 참고해보자.

 

결국 

[선택의 기준들에 대한 고민]

(ex. 빠르게 서비스 개발할 수 있는 Node.js.)

 

-개발 생산성이 좋아?

-성능이 좋고 안정적이야?

-개발자 커뮤니티는 활발해??

 

등등 기준에 따라 선택하면 되겠음.(최근은 웹서버 NGINX가 APACHE 에 비해 압도적이긴 함.