[웹서버]
웹서버는 정적인 자원만을 처리할 수 있다. (html, css) (Apache Http Server)
[CGI]
동적인 자원 즉 요청된 데이터로 어떤 프로그래밍 작업을 한 후 응답을 주는 니즈가 생김.
그래서 생긴게 CGI (Common Gateway Interface). (인터페이스다.)
이는 웹서버와 CGI 구현체 사이의 인터페이스 즉 규약이다.
웹서버에서 에서 동적인 응답을 받고, 자신이 처리하지 못해 CGI 구현체에게 줄 때의 규약이다.
[CGI 단점]
하지만 이 CGI 는 웹서버 -> CGI 구현체로 요청을 줄 때 한 요청당 프로세스를 만든다.
그리고, 한 프로세스마다 하나의 CGI 구현체를 사용한다.
따라서 한 요청에는 프로세스 한개, CGI 구현체 한개를 만들어 사용해야 한다.
- 프로세스 : 메모리에 적재된 하나의 프로그램 인스턴스. 즉 프로그램 하나당 메모리 할당을 따로 받는다.
- 스레드 : 한 프로세스 내의 작업 단위. 스레드들은 프로세스의 자원을 공유하기 때문에 생성하는 비용이 프로세스보다 적다. (따로 OS 에게 할당받지 않아도 됨.)
[CGI 단점을 해결한 Servlet]
CGI 의 단점 두가지를 고쳐보자.
- 프로세스 -> 스레드
- 하나의 프로세스당 하나의 CGI -> 여러 스레드당 하나의 서블릿 구현체 구현체
로 만든게 Servlet 구현체이다.
그리고 Servlet 이란건 웹서버와 서블릿 구현체 사이의 규약을 정해놓은 인터페이스 프로그램이다.
이 서블릿은 자바로 짜여진 인터페이스이다. (그래서 was 는 자바가 많다)
우리는 원하는 방식대로 이 서블릿의 구현체를 만들어서,
계산을 한다든지, DB 에서 값을 꺼내온다든지 등등의 동적인 처리 코드를 짠다.
[WAS - Servlet Container]
서블릿이란건 단지 코드일 뿐이다.
이를 실행시켜주는것이 WAS 이다.
- WAS = 서블릿 컨테이너 : 서블릿 구현체들이 만들어져 저장되는 곳이다.
- WAS 는 webserver 에게 동적 처리 요청을 받는다.
- WAS 는 요청당 스레드를 만들거나 스레드풀에서 받아 할당한다.
- 이 스레드는 이제 서블릿이 실행될 장소가 마련된 것이다.
- WAS 는 스레드에서 각 서블릿들을 실행한다.
[요청 ~ 서블릿 컨테이너 ~ 처리 흐름]
- 클라이언트에서 Http Request 전송.
- 동적 요청이라면, WebServer 가 WAS 에게 요청 넘김.
- WAS 는Servlet 실행 준비 및 실행. (아래는 WAS 가 하는 일임)
- HttpServletRequest, HttpServletResponse 객체 생성.
- 배포 서술자(Web.xml), 또는 에너테이션을 통해 요청 URL 과 맵핑된 서블릿 선정.
- 스레드를 생성하거나 스레드풀에서 스레드 잡음.
- 스레드에서 서블릿 실행.
- 새로 생성하는 서블릿이라면 init() - service() 순으로 호출.
- 보통 서블릿(인터페이스)은 객체를 한번 만든 후, 같은 요청들에 대해서는 재사용한다. (init() 호출 없이 service() 만.)
- 이 메서드 생성에서 HttpServletRequest, HttpServletResponse 객체를 인자로 넘겨줌.
- service() 메서드 에서는 요청에 맞게 doGet(), doPost(), doPut() 등의 메서드를 실행.
- 서블릿 동작과정에서 응답은 HttpServletResponse 에 기록해서 client 에게 반환.
- 종료 과정.
- 스레드 : 한 요청이 종료되면, 스레드는 반납되어 스레드풀로 다시 보내진다.
- HttpServletRequest, HttpServletResponse : 역할이 끝나고 가비지 컬렉션의 대상이 된다.
- Servlet : 서블릿은 한 서블릿의 여러 요청 스레드들이 모두 종료되거나, timeout 이 되면 destroy() 메서드를 호출해서 종료시킨다. 이 destroy() 메서드를 실행시키는 것은 WAS 이다.
이 과정에서 서블릿 구현체의 객체가 있어야 WAS 가 메서드를 실행시킬 수 있다.
서블릿 객체는 맵핑된 URL 에 대한 첫 요청시 생성되어, 여러 비동기적인 해당 URL 요청의 스레드들에 대해 재사용된다.
또, loadOnStartUp 속성을 이용하면 첫 요청시가 아니라, 컨테이너가 띄워질 때 미리 해당 서블릿 객체를 생성할 수 있다.
https://webfirewood.tistory.com/41?category=698497
[Spring 의 DispatcherServlet]
원래 서블릿은 URL 과 1:1 이다. 서블릿과 URL 맵핑정보는 배포서술자(Web.xml) 에 작성한다.
물론 한 URL 과 여러 비동기적 요청에 의해 생성된 스레드는 1:N 이다.
결국 [요청-URL-스레드-서블릿 = N:1:N:1] 이다.
요청마다 Setvlet 이 다르다면, 여러 Servlet 이 필요하다.
하지만 Spring 에서는 dispatcherServelt 이라는 특별한 Servlet 구현체를 사용한다.
이 서블릿은 모든 요청을 받는다.
그래서 Spring 에서는 Url 마다 서블릿을 만들 필요 없이, 서블릿 1개로 관리가 가능하다.
스프링 프로젝트를 만들어서 Web.xml 을 보면, dispatcherServelt 하나만 서블릿 등록이 되어있는걸 볼 수 있다.
스프링에서는 하나의 dispatcherServlet 이 뜨고, 이 안에서 메모리를 공유하는 여러 스레드들이 요청으로 들어오게 된다.
스프링은 dispatcherServlet 으로 요청을 받은 후, requestHandler 과 requestAdatper 등을 사용해서 컨트롤러와 연결시키는데, 이는 지금 다루지는 않겠다.
참고 : 테코톡
https://www.youtube.com/watch?v=2pBsXI01J6M
2. Nginx vs Apache
[구조]
Apache
- 아파치 웹서버는 다중처리 모듈(MPM. Multi-Processing Module) 방식을 사용하며, 대표적으로 2가지 종류가 있다.
- prefork : 요청이 들어오면 자식 프로세스를 관리하는 부모 프로세스가 자식 프로세스에 요청을 할당한다. 자식 프로세스는 하나의 스레드를 가지고 있다. 따라서 한 요청에 하나의 프로세스 전체를 쓰기에, 높은 성능을 요하는 요청에 유리하다.
- worker : prefork 방식과 비슷하지만, 자식 프로세스에 프로세스 자원을 공유하는 여러 스레드가 있다. 한 요청당 하나의 스레드를 차지한다. prefork 에 비해 자원을 적게 차지하고 프로세스를 띄우는 과정이 적기 때문에 시작 시간이 빠르다.
프로세스든 스레드든 정해진 한계만큼의 요청을 받을 수 있다. 그 이상의 요청은 받지를 못한다.
Nginx
- 엔진엑스는 Event-Driven 방식이다. 요청이 들어오면 아래 3단계에 의해 처리된다.
- Event Queue 에 요청이 쌓인다.
- Thread Pool 에는 작업을 처리할 스레드들이 모인다.
- Event Loop 에서는 EventQueue 에 들어온 요청을 Thread Pool 에서 작업가능한 Thread 에 비동기적으로 처리시킨다.
- 이런 이벤트 발행 방식은 여타 이벤트 방식처럼 관심사를 분리하여 느슨한 결합을 유지시킬 수 있다.
- 또, 아파치와 달리 nginx 의 자원과 상관없이 요청을 받을 수 있다. (큐에 쌓아놓으면 되니까.)
그리고 Nginx 는 프로세스가 아래와 같이 3가지가 있다.
- Master Process : config 파일을 읽고 검증, worker 프로세스를 관리
- Worker Process : 실제로 동작을 수행하는 프로세스. 위의 Event-Driven 방식으로 요청을 받아 처리한다.
- 다수의 워커 프로세스가 Nginx 설정에 의해 (CPU 코어 수에 맞게 설정되는게 디폴트) 생성된 후, 클라이언트의 요청이 늘어나는것에 상관없이 고정적으로 처리된다.
- Cache Process : 캐시 로더, 캐시 매니저
요청이 비동기적으로 처리되기 때문에, 동기적으로 처리할 때 주로 나타나는 컨텍스트 스위칭이 적다.
이 두 동작방식으로 미뤄봤을때,
Nginx 는 아래의 상황에서 유리하다 할 수 있다.
- 가벼운 작업. DB, Network, I/O 등의 작업들.
- 많은 요청이 들어와도 큐에 쌓아놓고 순차적으로 처리할 수 있고, 프로세스 기반이 아닌 스레드 기반이므로 생성시간이 짧아 빠르게 처리할 수 있다. 또, 한 프로세스의 여러 스레드들은 그 프로세스의 공유자원을 사용할 ㅜㅅ 있다.
=> Reverse Proxy 로 많은 곳에서 사용된다.
https://velog.io/@moonyoung/Nginx%EC%99%80-Apache
'TIL' 카테고리의 다른 글
TIL) EPSILON, 몽고 업데이트시 다른 컬럼 값 참조, 몽고 덤프 (0) | 2022.02.24 |
---|---|
TIL) 인덱스, DFA (0) | 2022.02.23 |
TIL) associate 시리즈 (0) | 2022.02.19 |
TIL) Enum, Memory Commit & OverCommit (0) | 2022.02.17 |
TIL) @Transactional Propagation, 스프링에서 초기화 코드를 넣기 (0) | 2022.02.17 |