본문 바로가기
Spring/Spring MVC

[Spring MVC] 3. Servlet Container와 멀티 쓰레드

by Kloong 2022. 11. 23.
더보기

Spring Boot & Thymeleaf 시리즈는 김영한 님의 "스프링 MVC 2편 - 백엔드 웹 개발 활용 기술" 강의를 정리한 글입니다. 글에 첨부된 사진은 해당 강의의 강의 자료에서 캡쳐한 것입니다. 제 Github에만 올려뒀다가, 정보 공유와 강의 홍보(?)를 위해 블로그에도 업로드합니다.

 

스프링 MVC 2편 - 백엔드 웹 개발 활용 기술 - 인프런 | 강의

웹 애플리케이션 개발에 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. MVC 2편에서는 MVC 1편의 핵심 원리와 구조 위에 실무 웹 개발에 필요한 모든 활용 기술들을 학습할 수 있

www.inflearn.com

 

마크다운 형식으로 작성한 글을 블로그에 다시 올리는 거라 가독성이 많이 떨어집니다. 조금더 편하게 보시려면 아래의 Github repository에서 보시면 됩니다.

 

GitHub - Kloong1/TIL: Today I Learned.

Today I Learned. Contribute to Kloong1/TIL development by creating an account on GitHub.

github.com

Servlet Container와 멀티 쓰레드

Servlet 객체를 누가 호출할까...?

사용자의 HTTP request가 오면 servlet 객체를 호출해서 로직을 실행해야 하는데, servlet 객체는 누가 호출할까? -> (당연한 소리긴 하지만)쓰레드가 호출한다.

쓰레드

  • 쓰레드는 애플리케이션 코드를 순차적으로 실행한다.
  • 자바 main method를 실행하면, main이라는 이름의 쓰레드가 생성되고 실행된다.
  • 쓰레드가 없다면 자바 애플리케이션을 실행할 수 없다.
  • 쓰레드는 한 번에 하나의 코드 라인을 실행할 수 있다.
  • 따라서 동시 처리가 필요하면 쓰레드를 추가로 생성해야 한다.

단일 요청 - 싱글 쓰레드

다중 요청 - 싱글 쓰레드

  • 싱글 쓰레드이기 때문에 쓰레드가 이미 요청을 처리하고 있다면(코드를 실행하고 있다면) 다른 요청은 해당 요청이 끝날 때 까지 기다려야 한다.
  • 처리중인 요청에 문제가 생겨서 처리가 지연이 된다면?
    • 다른 모든 요청은 해당 요청이 끝날 때 까지 기다려야 한다.

다중 요청 - 각 요청마다 새로운 쓰레드 생성

장점

  • 동시 요청을 처리할 수 있다.
  • 리소스(CPU, 메모리)만 충분하다면, 각 요청마다 새로운 쓰레드를 생성해서 처리 가능하다.
  • 하나의 쓰레드가 지연 되어도 나머지 쓰레드는 정상 동작한다.

단점

  • 쓰레드의 생성 비용은 매우 비싸다.
    • 고객의 요청이 올 때 마다 쓰레드를 생성하면 응답 속도가 늦어진다.
  • 쓰레드는 컨텍스트 스위칭 비용이 발생한다.
    • 쓰레드는 리소스만 충분하다면 계속 생성할 수 있지만 코어의 개수는 정해져 있다.
    • 쓰레드가 코어 개수보다 많아지면 많아질 수록 컨텍스트 스위칭 비용은 늘어난다.
  • 쓰레드 생성에 제한이 없다.
    • 고객 요청이 너무 많이 오면, CPU, 메모리 임계점을 넘어서 서버가 죽을 수 있다.

다중 요청 - 쓰레드 풀(Thread Pool)

  • Thread pool에 적당한 쓰레드를 미리 생성해서 대기시켜둔다.
  • 요청이 오면 쓰레드를 새로 생성하지 않고, 쓰레드 풀에 요청해서 이미 생성해 둔 쓰레드를 가져다 쓴다 (생성해둔 쓰레드에 작업을 할당한다)
  • 쓰레드가 요청을 다 처리했으면 제거하지 않고 쓰레드 풀에 다시 반납한다.
  • 요청이 들어왔는데 쓰레드 풀에 대기중인 쓰레드가 없다면?
    • 요청 대기를 하거나 거절하면 된다 (서버 설정에 따라 다르다. 최대 요청 대기 인원도 설정 가능하다)
  • 쓰레드 풀에 미리 생성된 쓰레드 수는 서버의 리소스 한계치를 넘지 않게 잘 설정해 둘 수 있기 때문에, 요청에 대한 새로운 쓰레드 생성에 의해 서버가 죽을 위험은 적다.

특징

  • 필요한 쓰레드를 쓰레드 풀에 미리 생성해두고 관리한다.
  • 쓰레드 풀에 생성 가능한 쓰레드의 최대치를 설정할 수 있다.
    • 톰캣의 경우 200개가 기본 설정이라고 한다.
  • 각 요청마다 새로운 쓰레드를 생성하는 경우의 단점을 보완할 수 있다.
    • 쓰레드 생성에 의한 응답 속도 저하 없음
    • 과도한 쓰레드 생성에 의한 문제들 해결(컨텍스트 스위칭 비용 증가, 서버 다운 등)

장점

  • 쓰레드가 미리 생성되어 있으므로, 쓰레드를 생성하고 종료하는 비용(CPU)이 절약되고, 응답 시간이 빨라진다.
  • 생성 가능한 쓰레드의 최대치가 있으므로 너무 많은 요청이 들어와도 기존 요청은 안전하게 처리할 수 있다.

쓰레드 풀 - 실무 팁

WAS의 주요 튜닝 포인트는 최대 쓰레드(max thread) 수이다.

  • Max thread 값을 너무 낮게 설정하면?
    • 동시 요청이 많으면, 서버 리소스는 여유롭지만 클라이언트는 금방 응답 지연을 겪는다.
  • Max thread 값을 너무 높게 설정하면?
    • 동시 요청이 많으면, CPU, 메모리 리소스 임계점 초과로 서버가 다운될 수 있다.
  • 장애 발생 시?
    • 클라우드면 일단 서버부터 늘리고, 이후에 튜닝한다.
    • 클라우드가 아니면 열심히 튜닝해야 한다.

 

  • Max thread 값을 너무 높게 설정해도 문제지만, 너무 낮게 설정해도 문제이다.
    • WAS는 정상 동작 중인데, 실제로 대부분의 고객들은 계속 서비스 장애를 겪는다.
  • 서버의 리소스를 최대한 활용하되, 서버가 다운되지 않을 정도의 max thread 값을 잘 설정해야 한다.

적정 max thread 값을 찾으려면?

  • 애플리케이션 로직의 복잡도, CPU, 메모리, IO 리소스 상황에 따라 모두 다르다!
    • 아무리 고수여도 대략적인 값을 추측할 수 있을 뿐이지 최적의 해를 바로 찾을 수는 없다.
  • 성능 테스트로 찾을 수 있다.
    • 최대한 실제 서비스와 유사하게 성능 테스트를 시도한다.
    • 성능 테스트 툴: Apache ab, JMeter, nGrinder

핵심: WAS가 멀티 스레드를 지원해준다!

  • 멀티 쓰레드에 대한 부분은 WAS가 처리해준다.
  • 개발자가 멀티 쓰레드 관련 코드를 신경쓰지 않아도 된다!
  • 개발자는 마치 싱글 쓰레드 프로그래밍을 하듯이 편리하게 소스 코드를 개발하면 된다.
    • 비즈니스 로직 개발에만 집중할 수 있다.
    • 생산성이 극대화된다.
  • 멀티 쓰레드 환경임을 염두에 두고 싱글톤 객체(서블릿, 스프링 빈)를 주의해서 사용해야 한다!
    • 객체의 멤버 변수 값이 공유 된다는 것을 주의해야 한다.

댓글