HTML Form 데이터를 전송할 때
웹 브라우저가 요청 메소드를 만들어서 서버에게 데이터를 보낸다.
이렇게 했을 때, 만약에 웹 애플리케이션 서버를 직접 다 구현해야 한다면?
우선, http message를 처음부터 끝까지 쭉 풀어 헤쳐야 한다.
기본적으로 TCP/IP로 연결 대기, 소켓을 연결한다.
단순 텍스트인 요청 http 메세지를 하나씩 다 자르고 파싱해서 읽게 된다.
그다음 post방식인지, save URL인지 확인하고 Content-Type을 확인한다.
http 메세지 바디 내용을 파싱하고 저장 프로세스를 실행한다.
.....
비즈니스 로직이 실행된다.
데이터 베이스에 저장을 요청한다.
.....
저장 프로세스 실행 후
저장이 잘 됐는지 http응답 메세지 생성을 시작한다.
그 후 TCP/IP에 응답을 전달해서 소켓을 종료한다.
이러한 과정이 서버를 직접 구현할 때 사용하는 방식인데,
실제로 개발의 과정에서는 비즈니스 로직 실행 부만 의미있는 비즈니스 로직이다.
그 전 후 단계가 너무 많고 똑같은 방식을 모두 다 해야하는것은 비효율적이다.
그래서 탄생한게 서블릿!
서블릿을 지원한 WAS는 비즈니스 로직을 제외한 모든 것을 자동으로 지원을 하게된다.
[서블릿]
urlPatterns(/hello)의 URL이 호출되면 서블릿 코드가 실행된다.
- HTTP요청 정보를 편리하게 사용할 수 있는 HttpServletRequest
- HTTP응답 정보를 편리하게 제공할 수 있는 HttpServletResponse
=> http message를 직접 파싱하지 않고 해당 요청, 응답 정보를 서블릿이 다 만들어 준다. http 스펙을 매우 편리하게 사용할 수 있도록 제공해준다. 원하는 데이터를 넣기만 하면 된다.
단, HTTP 스펙은 꼭 인지해야한다!
웹 브라우저에서 http 요청 메서드를 새로 만든 후 우리가 만든 서블릿을 서블릿 컨테이너에서 실행을 시켜준다.
HTTP 요청시,
WAS는 request, response 객체를 새로 만들어서 서블릿 객체 호출을 한다.
개발자는 요청 객체에 HTTP요청 정보를 편리하게 꺼내서 사용할 수 있게 된다.
개발자는 응답 객체에 HTTP응답 정보를 편리하게 입력한다.
WAS는 응답객체에 담겨잇는 내용으로 HTTP응답 정보를 생성 후 웹 브라우저에게 전달한다.
웹 브라우저는 전달받은 응답으로 렌더링 후 화면을 보여주게 된다.
서블릿을 지원하는 WAS안에는 서블릿 컨테이너가 존재한다.
[서블릿 컨테이너]
톰캣처럼 서블릿을 지원하는 WAS를 서블릿 컨테이너라고 한다.
서블릿 객체를 서블릿 컨테이너가 자동으로 생성, 호출, 생명주기를 관리한다.
서블릿 객체는 싱글톤으로 관리한다.
- 처음에 딱 하나만 생성한 객체를 모두가 공유해서 쓰는 방식
- 고객 요청이 올 때마다 계속 객체를 생성하는 것은 비효율적이다.
- 최초 로딩 시점에 서블릿 객체를 미리 만들어두고 재활용한다.
- 모든 고객 요청은 동일한 서블릿 객체 인스턴스에 접근한다.
- 단, 공유 변수 사용에 주의해야 한다. -> 멤버변수에 값이 있을 경우는 주의해서 사용한다.
- 서블릿 컨테이너 종료시 함께 종료된다.
JSP도 서블릿으로 변환되어서 사용된다.
동시 요청을 위한 멀티 쓰레드처리를 지원한다.
가장 큰 특징 서버가 동시에 여러명이 요청을 오는 것을 잘 처리하는데 이것이 바로 멀티 쓰레드이다.
동시 요청 - 멀티 쓰레드
백엔드에서 가장 중요한 개념이다.
서블릿 객체를 도대체 누가 호출하지?
바로 쓰레드가 호출하는 것이다.
애플리케이션 코드를 하나하나 순차적으로 실행하는 것을 쓰레드라고 하고(프로세스는 프로그램을 실행하는것)
자바 메인 메서드를 처음 실행하면 main이라는 이름의 쓰레드가 실행된다.
쓰레드가 없다면 자바 애플리케이션 실행이 불가능하다.
쓰레드는 한번에 하나의 코드 라인만 실행한다.
동시 처리가 필요하면 쓰레드를 추가로 생성해줘야 한다.
만일 쓰레드가 한개만 있을 경우, 요청이 하나가 왔을 때 쓰레드를 할당하고 서블릿 코드를 실행 후 응답을 한다.
다중 요청의 경우? 쓰레드를 써서 서블릿을 처리하는데 요청 처리 중에 처리가 지연되고 있을 때 동시에 다른 요청이 들어왔다고 한다면 어떻게 해야할까? 쓰레드는 한개 뿐이라 후자로 온 요청은 기다리게 되고 결국은 요청1, 요청2는 수행 자체를 못하고 타임아웃, 모두 죽게 된다.
단순한 방법이 있다.
쓰레드 하나 더 생성하면 되는 것이다.
요청 1번의 처리지연 중이더라도 요청2가 오면 신규 쓰레드를 생성 후 서블릿을 실행하면 된다.
이렇게 요청이 올떄마다 새로운 쓰레드를 만들고 요청이 끝나면 쓰레드를 날리면 된다.
was가 이런식으로 구현을 해줘도 되지만 요청이 올때마다 생성하면 응답 속도가 늦어진다.
장점:
동시 요청 처리를 할 수 있다.
리소스(cpu, 메모리)가 허용할 때까지 가능
하나의 쓰레드가 지연되어도, 나머지 쓰레드는 정상 동작한다.
단점:
쓰레드 생성 비용은 매우 비싸다.
- 고객의 요칭이 올 떄마다 쓰레드를 생성하면 응답 속도가 느려짐
쓰레드는 컨텍스트 스위칭 비용이 발생한다.
- 쓰레드가 많아지면 비용자체가 점점 커진다.
쓰레드 생성에 제한이 없다.
- 고객요청이 많이오면 CPU, 메모리 임계점을 넘어서 서버가 죽을 수도 있다.
이러한 단점을 보안하기 위해서 있는 것이 쓰레드 풀이다.
[쓰레드 풀]
요청마다 쓰레드 생성의 단점을 보완할 수 있는 쓰레드 풀이란?
내부에 풀장에서 쓰레들이 놀고 있다가 요청이 오면 놀고있는 쓰레드를 콜한다.
다쓰면 사용한 쓰레드는 다시 쓰레드 풀에 반납을 한다.
쓰레드를 죽이고 생성하는 것이 아닌 풀안에 미리 만들어 놓고 빌려쓰고 반납을 한다.
특징:
- 필요한 쓰레드를 쓰레드 풀에 보관하고 관리한다.
- 톰캣은 최대 200개 기본 설정(변경 가능) 쓰레드 풀에 가능한 쓰레드의 최대치를 관리한다.
사용:
- 쓰레드가 필요하면 이미 생성되어 있는 쓰레드를 쓰레드 풀에서 꺼내서 사용한다.
- 사용을 종료하면 풀에 쓰레드를 반납한다.
- 최대 쓰레드가 모두 사용중이서 쓰레드 풀에 쓰레드가 없다면?
기다리는 요청은 거절하거나 특정 숫자만큼 기대하도록 설정할 수 있다.
장점:
- 쓰레드가 미리 생성되어 있으므로, 쓰레드를 생성하고 종료하는 비용(CPU)이 절약되고, 응답 시간이 빠르다.
- 생성 가능한 쓰레드의 최대치가 있으므로 너무 많은 요청이 들어와도 기존 요청은 안전하게 처리할 수 있다.
실무 팁
- WAS의 주요 튜닝 포인트는 최대 쓰레드(max thead) 수이다.
- 이 값을 너무 낮게 설정하면? 동시 요청이 많으면 서버 리소스는 여유롭지만 클라이언트는 금방 응답 지연된다.
예를 들어 동시 10개만 처리 가능하도록 설정했을 때, 요청이 100개가 왔다면 10개는 실행중 90개는 대기 중
맥스 쓰레드 자체를 너무 낮게 잡으면 요청이 계속 쌓이게 되고 서비스 장애가 올 수 있다.
ex) CPU를 5%만 사용하게 됨
- 이 값을 너무 높게 설정하면? 동시 요청이 많으면 CPU, 메모리 리소스 임계점 초과로 서버가 다운될 수 있다.
10,000개 요청을 설정하면 10, 000 요청을 다 받아들이게 됨 결국 서버가 다운된다. 중요한 것은 적정값을 찾아서 설정하는 것이 중요하다.
장애 발생시?
- 서버부터 늘리고 이후에 튜닝을 해야한다.
쓰레드 풀의 적정 숫자
- 애플리케이션 로직의 복잡도, CPU, 메모리, IO 리소스 상황에 따라 모두 다르다.
- 중요한것은 성능 테스트
최대한 실제 서비스와 유사하게 성능 테스트 시도
툴: 아파치 ab, 제이미터, nGrinder
오픈 전에 고객트래픽이 좀 있는 서비스라면 성능 테스트를 해봐야 한다.
WAS의 멀티 쓰레드 지원 핵심
- 멀티 쓰레드에 대한 부분은 WAS가 처리한다.
- 개발자는 멀티 쓰레드 관련 코드를 신경쓰지 않아도 된다.
- 개발자는 마치 싱글 쓰레드 프로그래밍을 하듯이 편리하게 소스 코드를 개발한다.
- 멀티 쓰레드 환경이므로 싱글톤 객체(서블릿, 스프링 빈)는 주의해서 사용한다.
서블릿 코드에 비즈니스 로직만 넣어주면 됨! 나머지는 다 멀티쓰레드가 처리해 줌!
WAS가 개발 생상성을 높여주는 부분임!
'TIL' 카테고리의 다른 글
TIL - 스택 (0) | 2025.01.07 |
---|---|
TIL - 배열과 연결리스트 (0) | 2025.01.02 |
자료구조와 알고리즘이란? (0) | 2024.12.29 |
댓글