서블릿 컨테이너와 쓰레드

🌟 멀티쓰레드 지원 및 관리
서블릿 컨테이너는 요청이 들어올 때마다 새로운 쓰레드를 생성해 동시 요청을 처리할 수 있도록 한다.
쓰레드는 HTTP 메서드를 통해 요청을 처리한 후 자동으로 죽도록 해 안정적으로 관리한다.

 

그러나 쓰레드를 생성하는 것은 꽤나 큰 비용을 요구한다.

그럼에도 불구하고 매번 쓰레드를 생성하는 이유는 무엇일까?

💡 동시 요청 처리

결론적으로, 서블릿 컨테이너가 멀티쓰레드를 지원하는 것은 동시다발적으로 들어오는 요청을 처리하기 위함이다.

 

자바 애플리케이션은 최소 하나 이상의 쓰레드를 가지고 있다.

기본적으로는 프로그램을 실행하면 메인쓰레드가 생성되고 그 위에 메인메서드를 적재한다.

하나의 쓰레드에서는 한번에 하나의 코드라인만 수행할 수 있다.

한번에 여러 코드라인을 수행하기 위해서는 쓰레드를 추가해야 한다.

 

다시말해, 하나의 쓰레드는 한번에 하나의 요청만을 처리할 수 있다.

여러 요청을 동시에 처리하기 위해서는 여러개의 쓰레드가 필요하다.

☝️ 단일 요청 처리

단일 요청을 처리할 때에는 싱글쓰레드 환경도 문제없을 것이다.

싱글쓰레드 환경에서 하나의 요청을 처리하는 과정을 살펴보자.

 

  • 클라이언트로부터 요청이 오면, WAS는 쓰레드를 할당한다.
  • 쓰레드는 서블릿 메서드를 호출해 요청을 처리한다.

 

  • 응답을 처리한다.

 

  • 작업을 마친 쓰레드는 종료된다.

✌️  다중 요청 처리

싱글쓰레드

단일 요청 처리와 마찬가지로 싱글쓰레드 환경에서 요청을 처리해보자.

 

  • 요청1을 처리하는 도중 요청2가 들어온다.
  • 요청2는 대기하다가 쓰레드의 요청1 처리가 끝나면 처리를 시작한다.

 

그런데, 요청1을 처리하던 중 처리 지연이 발생하면 어떻게 될까?

 

  • 요청1을 처리하던 중 서블릿에서 처리 지연이 발생했다.
  • 이 상태에서 요청2가 들어온다.

 

  • 동시 요청으로 인해 모든 요청이 죽게된다.

⭐️ 멀티 쓰레드 환경

그렇다면 멀티쓰레드 환경에선 어떨까?

 

  • 요청2가 들어오면 서블릿 컨테이너는 새로운 쓰레드를 생성하고 대기 없이 요청을 실행한다.
  • 요청1에 대한 처리 지연이 발생해도, 쓰레드2는 정상적으로 서블릿 메서드를 실행한다.

 

이처럼 멀티쓰레드 환경에서는 동시적으로 들어오는 요청을 즉각적으로 처리할 수 있다.

또한 각각의 쓰레드는 독립적으로 동작하기 때문에 처리 지연이나 오류가 발생해도 다른 요청 처리에 영향을 미치지 않는다.

 

그렇지만 앞서 언급한 것처럼 매번 쓰레드를 생성하게 되면 응답 속도가 늦어진다.

또한 쓰레드는 작업 전환에 시간이 소요되므로, 이러한 스위칭 비용도 고려해야 한다.

제한없이 쓰레드가 생성되면 어느 순간 메모리 임계점을 넘어 서버가 다운될 수 있는데, 한번 죽은 서버는 복구하기 매우 어렵다.

 

이러한 문제점을 해결하기 위해 서블릿 컨테이너는 쓰레드 풀을 사용한다.

📁 쓰레드 풀 Thread Pool

서블릿 컨테이너에서 쓰레드를 담아두는 공간

쓰레드 풀은 요청마다 쓰레드를 생성하는 서블릿 컨테이너의 단점을 보완하는 역할을 한다.

 

컨테이너는 쓰레드 풀에 생성 가능한 쓰레드의 최대 개수를 설정해 미리 생성해놓고 관리한다.

톰캣의 경우 기본적으로 200개의 쓰레드를 만들 수 있고, 필요에 따라 변경 가능하다.

장점

  • 쓰레드가 이미 생성되어 있으므로 요청이 들어올 때마다 쓰레드를 생성하는 비용이 절감된다.
  • 생성 가능한 쓰레드 수가 제한되어 있으므로 서버의 과부하를 방지한다.

동작 과정

  • 쓰레드 풀에는 이미 쓰레드가 생성되어 있다.
  • 요청이 들어오면 쓰레드 풀에 생성된 쓰레드를 사용해 요청을 처리한다.
  • 요청을 처리한 후에는 쓰레드 풀에 쓰레드를 반납한다.

 

  • 이미 들어온 요청들이 쓰레드 풀의 모든 쓰레드를 사용중이다.
  • 남은 쓰레드가 없어 새로 들어오는 요청은 대기하거나 거절된다.

🤔 최대 쓰레드 수

쓰레드 풀에서 가장 중요한 것은 최대 쓰레드 수이다.

 

너무 낮게 설정하는 경우 서버 리소스는 여유롭지만, 응답 처리가 지연될 수 있다.

프로그램 내부적으로는 정상적으로 동작하고 있지만 외부 사용자는 응답이 지연되고 밀리면서 장애를 경험하게 된다.

그렇다고 너무 높게 설정하면 CPU와 메모리 임계점을 초과해 서버가 다운될 수 있다.

따라서 성능테스트를 통해 적절한 max-thread를 설정해야 할 것이다.