Lined Notebook

[스프링 MVC - 백엔드 웹 개발 기술] 02. 동시 요청 - 멀티 쓰레드

by ymkim

01. 동시 요청 - 멀티 쓰레드

01-1. 쓰레드

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

01-2. 단일 요청 쓰레드 하나 사용

Client 요청이 있기 전 Thread는 대기 상태에 있다
Client Was(Web Application Server)에 요청을 보내고, Thread가 Servlet을 호출한다
요청에 대한 처리가 완료되면 Client에게 응답 한다

 

Thread는 다시 대기 단계에 들어가게 된다

  1. WAS 내의 쓰레드는 현재 요청을 받지 않기에 휴식 단계
  2. Client 요청 시 연결(Connection)이 수행되고 해당 연결에 쓰레드가 할당된다
  3. 이렇게 연결된 쓰레드가 서블릿(Servlet)을 호출한다
  4. 요청 처리를 다 하면 Client에게 응답(Response)을 하고 쓰레드는 다시 휴식에 들어간다

01-3. 다중 요청 쓰레드 하나 사용

  1. Client 01번이 WAS에 요청을 수행하고 해당 요청이 Thread에 연결된다
  2. 서블릿(Servlet)이 해당 요청을 바로 처리하면 좋겠지만 현재 처리 지연이 발생한 상황이다
  3. 이 때 다음과 같이 Client 02번이 요청을 수행한다

  1. 현재 Client 02번은 Client 01번의 요청이 끝나지 않았기 때문에 대기 상태 에 있는 상황이다
  2. 위 같은 경우 Client 01번의 요청 종료를 계속 기다려야 하기 때문에 둘 다 disconnected 될 확률이 높다

어떻게 문제를 해결해야 할까? “답은 스레드를 하나 더 생성하면 된다” 이다.

  1. 위에서 말했다시피 Client 02번은 Client 01번의 요청 여부와 상관 없이 동작 한다
  2. 즉, 새로운 쓰레드(Thread)가 생성이 되고 해당 쓰레드(Thread)를 통해 Servlet을 호출한다

01-4. 요청 마다 쓰레드 생성의 장단점

  • 장점
    • 동시 요청 처리 가능
    • 리소스(CPU, Memory)가 허용할 때까지 처리 가능
    • 하나의 쓰레드가 지연 되어도 나머지 쓰레드 정상 동작
  • 단점
    • 쓰레드 생성 비용은 상당히 비쌈
      • 고객 요청마다 쓰레드 생성하면 응답 속도가 느려짐
      • 쓰레드 생성 시 CPU를 많이 쓴다
    • 쓰레드는 컨텍스트 스위칭 비용 발생
    • 쓰레드 생성에 제한이 없음
      • 고객 요청이 너무 많이 오면 CPU, Memory 임계점 넘어서 서버 뻗을 수 있음

작년에 부하테스트를 그렇게 했음에도 불구하고 ECS의 CPU, Memory를 잘못 산정하여
ECS가 죽은 경험이 있었다… 꼭 많은 쓰레드를 사용하는 것이 좋은 것만은 아닌 것 같다…

01-5. WAS는 내부적으로 쓰레드 풀을 갖는다

쓰레드풀은 요청마다 쓰레드를 생성하는 것은 비효율적이기에 사용이 된다.

  1. WAS 기본적으로 내부에 Thread Pool을 가지고 있음
  2. Client 01이 요청을 하게 되면 해당 TCP/IP 연결이 Thread Pool에 Thread(쓰레드)를 요청한다
  3. 또 Client 02이 요청을 하여 Thtread Pool에 Thread(쓰레드)를 요청한다
  4. Client 01, 02번의 요청을 다 처리하면 다시 Thtread Pool에 Thread를 반환 한다
  5. 검색 API쪽 개발 및 운영을 담당하는 입장으로써 API 지연 현상은 너무 자주 발생하는 현상이다..

작년 12월 말에 5대의 서버에서 수용할 수 있는 리소스를 넘는 트래픽이 들어온 경험이 있다. 그래서 ECS Container의 API의 Thread 갯수를 200개에서 → 262개로 조정을 한 경험이 존재한다..

01-6. 쓰레드 풀 - 요청마다 쓰레드 생성의 단점 보완

  • 특징
    • 필요한 쓰레드를 쓰레드 풀(Thread Pool)에 보관 및 관리
    • 쓰레드 풀(Thread Pool)에 생성 가능한 쓰레드 최대치 관리 (톰캣은 최대 200개 기본 설정)
  • 사용
    • 쓰레드 필요 이미 생성된 쓰레드 풀(Thread Pool)에서 꺼내 사용
    • 사용 종료 시 쓰레드 풀(Thread Pool)에 반환
    • 최대 쓰레드가 모두 사용중 → 쓰레드 풀에 쓰레드 없음?
      • 연결을 끊어버리거나 대기하도록 설정 가능
  • 장점
    • 쓰레드가 미리 생성되어있어 리소스(CPU, Memory) 절약, 응답 시간 빠름
    • 쓰레드 최대치가 있어 과한 트래픽이 들어와도 기존 요청 안전하게 처리 가능

01-7. 쓰레드 풀 - 실무 팁

  • WAS의 주요 튜닝 포인트 → 최대 쓰레드(max thread) 수이다
    • 필자는 undertow WAS를 사용중인데, yml 파일에 max-thread 설정을 한 경험이 있음
    server:
      port: 10091
      undertow:
        io-threads: 16
        worker-threads: 200
    
  • 최대 쓰레드 수가 너무 낮으면?
    • 서버 리소스는 여유롭지만, 클라이언트는 응답 지연
  • 최대 쓰레드 수가 너무 높으면?
    • 트래픽 많으면 서버 리소스(CPU, Memory) 임계점 초과로 서버 터짐
  • 장애 발생 시?
    • 클라우드 → 서버 증설 → 이후 성능 튜닝
    • 클라우드 x → 열심히 성능 튜닝

01-8. 쓰레드 풀 - 쓰레드 풀의 적정 숫자를 어떻게 산정?

  • 애플리케이션 로직 복잡도, CPU, Memory, IO 리소스 상황에 따라 다름
  • 성능 테스트
    • 최대한 실제 서비스와 유사하게 성능 테스트 시도
    • 툴: 아파치 ab, jmeter, nGrinder

01-9. 핵심) WAS의 멀티 쓰레드 지원

  • 멀티 쓰레드에 대한 부분은 WAS가 처리
  • 개발자는 멀티 쓰레드 관련 코드 신경쓰지 않아도 됨
  • 개발자는 마치 싱글 쓰레드 프로그래밍을 하듯이 편리하게 소스 코드 개발
  • 멀티 쓰레드 환경이므로 싱글톤 객체(서블릿, 스프링 빈)은 주의해서 사용 필요

블로그의 정보

기록하고, 복기하고

ymkim

활동하기