스레드와 스레드 풀

작성일

스레드

스레드란 프로세스의 자원을 이용해서 실제로 작업을 수행하는 것

  • 애플리케이션 코드를 하나하나 순차적으로 실행하는 것
  • 자바 메인 메서드를 처음 실행하면 main이라는 이름의 스레드가 실행
  • 스레드가 없다면 자바 애플리케이션 실행이 불가능함
  • 스레드는 한번에 하나의 코드 라인만 수행
  • 동시 처리가 필요하면 스레드를 추가로 생성

참고
클라이언트에서 요청이 들어온 경우 WAS와 연결을 해주는 역할을 TCP/IP 에서 해준다. TCP/IP를 통해 요청한 주소를 통해 WAS와 연결이 되고 연결된 요청을 WAS에서 스레드를 사용하여 적절한 Servlet으로 처리를 해준다.

요청마다 하나의 스레드를 생성한다고 가정하면,

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

그러나, 스레드는 생성 비용이 매우 비싸고 요청마다 하나의 스레드를 생성하면 응답 속도가 늦어진다. 또한, 스레드는 컨텍스트 스위칭 비용이 발생한다. 컨텍스트 스위칭 비용이란 스레드를 전환할때 발생하는 비용을 말하는데 스레드가 너무 많으면 문제가 생긴다. 스레드 생성 시 CPU, 메모리가 사용되는데 그 임계점을 넘어서 서버가 죽을 수도 있다.

이러한 단점들은 보완한 것이 스레드 풀이다.

참고
멀티 스레드에서의 동시 요청과 다수 서버로 운영되는 어플리케이션에서의 동시 요청은 같은 맥락이 아니다. 멀티 스레드는 하나의 서버 안에서 발생하는 것을 전제로 얘기한다. 여러 대의 서버로 구성된 서비스가 동시 요청을 처리하는 건 로드 밸런서라는 키워드가 있다.

스레드 풀

스레드 풀에 필요한 스레드를 보관하고 관리하며 스레드 풀에 생성 가능한 스레드의 최대치를 관리한다. (톰캣의 경우 최대 200개)

스레드가 필요하면 스레드 풀에 이미 생성되어 있는 스레드를 꺼내서 사용하고 사용을 종료하면 스레드 풀에 해당 스레드를 반납한다. 만약, 최대 스레드가 모두 사용중이여서 스레드 풀에 스레드가 없다면 기다리는 요청은 거절하거나 특정 숫자만큼만 대기하도록 설정 할 수 있다.

스레드 풀의 장점은 스레드가 미리 생성되어 있으므로, 스레드를 생성하고 종료하는 비용이 절약되고 응답 시간이 빠르다. 또한, 생성 가능한 스레드의 최대치가 있으므로 너무 많은 요청이 들어와도 기존 요청은 안전하게 처리할 수 있다.

스크린샷 2022-06-04 오후 7 01 17

스레드 풀과 관련된 실무팁

WAS의 주요 튜닝 포인트는 최대 스레드(max thread) 수이다. max thread를 낮게 설정 시 동시 요청이 많으면 서버 리소스는 여유롭지만, 클라이언트는 금방 응답 지연된다. max thread를 높게 설정 시 동시 요청이 많으면 CPU, 메모리 리소스 임계점 초과로 서버가 다운된다.

그럼 스레드 풀의 적정 숫자가 뭘까? 이에 대한 정답은 없다. 애플리케이션 로직의 복잡도, CPU, 메모리, IO 리소스 상황에 따라 모두 다르다. 적정 숫자를 찾을 방법은 최대한 실제 서비스와 유사하게 환경을 구성 후 성능 테스트를 시도하는 것이다. 관련 툴로는 아파치 ab, 제이미터, nGrinder가 있다.

장애가 발생했다고 가정하고, 클라우드면 일단 서버부터 증설하고 이후에 튜닝을 하고 클라우드가 아니면 열심히 튜닝..해야 한다.

참고
스레드 풀을 사용해도 컨텍스트 스위칭 비용이 발생한다. 그러나, 무한정 늘어나지 않으니 컨텍스트 스위칭 비용도 무한정 늘어나지 않는다.

참고
서버가 다운되었을 경우 우선 점검 페이지로 요청을 돌린다. 그 후 다운되는 원인을 찾는다. 다운되는 원인은 connection pool timeout, memory leak 등 여러 이유가 있다. 모니터링 툴을 통해 원인을 찾아낼 수도 있고, 힙 덤프를 떠서 살펴보는 방법도 있다. 코드 레벨에서 해결할 수 있는 문제는 조치 후 운영하면 되고 물리적인 문제라면 서버 증설을 빠르게 진행한다.

참고 AWS의 AutoScaling
AWS에는 AutoScaling이란 기능이 있어 요청이 증가할 때 자동으로 인스턴스를 생성하여 늘어나는 요청에 대응할 수 있다. 하지만, 순간적으로 요청이 폭발적으로 증가하는 경우에는 대응하기 어려울 수 있다. 인스턴스가 생성되는 시간이 필요하기 때문!. 예측할 수 있는 이벤트의 경우 미리 인스턴스를 확보하여 늘어나는 요청에 대응하기도 한다.

참고 톰캣 스레드와 JPA에서 사용하는 스레드
스레드는 어떠한 프로그램, 프로세스 내에서 실행되는 하나의 흐름을 의미한다. 톰캣은 웹서버로써 고객의 HTTP 요청을 처리하는 프로세스를 담당하며 이를 효율적으로 처리하기 위한 스레드풀을 운영한다. JPA도 하나의 프로세스로 스프링 컨테이너와 DB 사이에서의 중계자 역할을 맡고 있다. JPA 또한 업무 효율을 위한 스레드풀을 별도로 운영한다. (보통 HikariPool 이라고 하는 스레드풀 라이브러리를 사용한다.) 이 둘의 스레드는 별도로 관리되기에 서로 영향을 미치지 않는다. 단, 어떤 HTTP 요청이 많은 DB 조회를 요구한다면 톰캣의 스레드 1개와 JPA 스레드 여러개를 차지할 수 있다.