Notice
Recent Posts
Recent Comments
Link
관리 메뉴

look-forest

Servlet과 멀티스레딩 본문

Spring/Spring MVC - 웹 개발 핵심 기술

Servlet과 멀티스레딩

studyHub 2021. 5. 31. 23:02

Java 기반 웹 애플리케이션을 개발할 때, 서블릿을 사용한다.

Java에서는 서블릿 컨테이너 기능을 제공하면 WAS라고 한다.

서블릿은 무엇이며 왜 필요한지 알아보자.


서블릿은 왜 필요한가

HTTP 메시지를 받았을 서버에서 처리해야 하는 업무

TCP/IP 연결부터 HTTP 요청 메시지 파싱, HTTP 응답 메시지 생성, 연결 종료 등 할 게 참 많다.

 

애플리케이션 서버를 직접 구현해야 한다면 노가다를 다해야..

그러나 서블릿을 지원하는 WAS 사용한다면, 비즈니스 로직을 제외한 모든 작업을 다 지원해준다!

(직접 TCP/IP 소켓 프로그래밍하고 HTTP 메시지를 파싱하고 만들지 않아도 된다!)

 

서블릿이란?

서버에서 실행되는 자바 프로그램.

클라이언트의 요청에 대해 동적으로 작동하는 웹 어플리케이션 컴포넌트.

추상적이다..

백문이 불여일견! 아래와 같은 코드로 구성된 것이 서블릿이다.

HttpServlet 클래스를 상속 받아 비즈니스 로직을 적는다

  • URL 클래스를 맵핑하여, URL 호출되면 서블릿 코드가 실행된다.
  • HTTP 요청 정보를 편리하게 사용 있는 HttpServletRequest
  • HTTP 응답 정보를 편리하게 제공 있는 HttpServletResponse

이처럼 서블릿을 통해, 개발자는 HTTP 스펙을 매우 편리하게 사용 있게 된다.

 

개발자는 서블릿에 로직만 짜두면 된다.

그럼 WAS 안의 서블릿 컨테이너가 서블릿을 생성하고 호출해준다.

 

※ JSP도 서블릿으로 변환되어서 사용된다.

 

HTTP 요청, 응답 흐름

실제 요청, 응답 과정 속에서 서블릿이 어떻게 동작하는지 살펴보자.

  1. WAS Request, Response 객체를 새로 만들어서 서블릿 객체 호출
  2. 개발자는 Request 객체에서 HTTP 요청 정보를 편리하게 꺼내서 사용 (서블릿 코드 안)
  3. 개발자는 Response 객체에 HTTP 응답 정보를 편리하게 입력 (서블릿 코드 안)
  4. WAS Response 객체에 담겨있는 내용으로 HTTP 응답 정보를 생성

서블릿에 담겨 있는 로직을 실행한다

 

서블릿 컨테이너

톰캣처럼 서블릿을 지원하는 WAS 서블릿 컨테이너라고 한다.

 

1. 서블릿 컨테이너는 서블릿 객체를 생성, 초기화, 호출, 종료하는 생명주기를 관리한다.

2. 서블릿 컨테이너는 서블릿 객체를 싱글톤으로 관리한다

   - 요청이 때 마다 객체를 생성하는 것은 비효율적이므로, 최초 로딩 시점에 서블릿 객체를 미리 만들어두고 재활용 

   - 따라서 모든 고객 요청은 동일한 서블릿 객체 인스턴스에 접근하게 된다.

   - 때문에 공유 변수 사용에 주의해야 한다

3. 동시 요청을 위한 멀티 쓰레드 처리 지원한다

 


동시 요청 - 멀티 쓰레드

Q. 서블릿 객체(싱글톤)는 누가 호출해주지?

A. 스레드가 서블릿 객체를 호출해준다!

 

쓰레드란?

CPU 작업 요청을 하는 실행 단위, 프로세스를 작은 단위로 나눈 것.

애플리케이션 코드를 하나하나 순차적으로 실행.

 

  • 자바 메인 메서드를 처음 실행하면 main이라는 이름의 쓰레드가 실행된다.
    쓰레드가
    없다면 자바 애플리케이션 실행이 불가능하다.
  • 쓰레드는 한번에 하나의 코드 라인만 수행한다.
    동시 처리가 필요하면 쓰레드를 추가로 생성해야 한다.
  • 프로세스 vs 스레드
    - 프로세스: 프로그램을 실행한
    - 스레드: 프로세스 안에서 여러 갈래로 나뉘는

멀티스레드

단일 스레드 사용 시 문제점

단일 요청 시엔 문제가 없으나..

HTTP 연결이 되면 스레드가 할당되고, 스레드가 서블릿을 호출한다

다중 요청 시, 유일한 스레드의 처리가 지연된다면 줄줄이 다 죽게 된다..

죄없는 요청2는 기다리다가 Time out 발생으로 실패

 

뭐.. 요청마다 스레드를 생성하면 당장 해결되긴 한다

하나의 스레드가 지연 되어도 나머지 스레드는 정상 동작하며, 동시 요청을 처리할 수 있다 .

 

그러나, 요청마다 스레드 생성하는 것은 여러 단점이 있다.

1. 스레드는 생성 비용이 매우 비싸다는 것.

   고객의 요청이 때마다 스레드를 생성하면, 그만큼 응답 속도가 늦어진다

2. 스레드는 컨텍스트 스위칭 비용 발생한다.

   ※ CPU 코어 수만큼 스레드가 동시에 돌아가는데, 코어마다 여러 스레드를 빠르게 전환할 때의 비용

3. 스레드 생성에 제한이 없다.

   고객 요청이 너무 많이 오면, CPU, 메모리 임계점을 넘어서 서버가 죽을 있다.

 

 

그래서 WAS 스레드 풀을 쓴다

스레드 : 필요한 스레드를 미리 만들어 스레드 풀에 보관하고 관리한다

DBCP처럼 미리 만들어두고 꺼내 쓴다

  • 쓰레드가 필요하면, 이미 생성되어 있는 쓰레드를 쓰레드 풀에서 꺼내서 사용한다
    쓰레드가
    미리 생성되어 있으므로, 쓰레드를 생성하고 종료하는 비용(CPU)이 절약되고, 응답 시간이 빠르다
  • 사용을 종료하면 쓰레드 풀에 해당 쓰레드를 반납한다.
  • 현재 가용 쓰레드가 없으면, 기다리는 요청은 거절하거나 특정 숫자만큼만 대기하도록 설정할 있다
    생성
    가능한 쓰레드의 최대치가 있으므로 너무 많은 요청이 들어와도 기존 요청은 안전하게 처리 있다

 

WAS 멀티 스레드 지원 기능

멀티 스레드에 대한 부분은 WAS 처리해주기 때문에, 개발자가 멀티 스레드 관련 코드를 신경쓰지 않아도 된다!

싱글 스레드 프로그래밍을 하듯이 편리하게 소스 코드를 개발할 있다!

그저 서블릿 코드 안에 비즈니스 로직만 넣으면 된다!

다만, 멀티 스레드 환경이므로 싱글톤 객체(서블릿, 스프링 ) 주의해서 사용하자!

 

 

※ 스레드 풀 실무 팁
트래픽이 많을 때, 스레드 풀의 최대 스레드 수를 튜닝해야 한다.

- 너무 낮게 설정하면, 서버 리소스 사용량도 낮고, 클라이언트는 금방 응답이 지연된다.
  예) 요청 100개 중 10개밖에 처리 못함, CPU 사용량은 5%.. 서버를 증설하면 돈 낭비..

- 너무 높게 설정하면, CPU, 메모리 리소스 임계점 초과로 서버가 다운될 수 있다.

적정 숫자는 성능 테스트를 통해 찾는다.
적정 숫자는 애플리케이션 로직의 복잡도, CPU, 메모리, IO 리소스 상황에 따라 모두 다르기 때문에,
결국 최대한 실제 서비스와 유사하게 성능 테스트 시도해야 된다.
(tool: 아파치 ab, 제이미터, nGrinder)

장애가 발생했을 경우,
클라우드면 일단 서버부터 늘리고, 이후에 튜닝. (클라우드의 장점..!)
클라우드가 아니면 열심히 튜닝.. 

 

 


참고 자료 & 이미지 출처
스프링 MVC 1편(김영한 님)