Spring/스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술

3. 동시 요청 - 멀티 쓰레드 (쓰레드 풀)

DEV-HJ 2023. 9. 9. 23:10
반응형

백엔드 개발자는 이게 진짜 중요하다.

이거에 대한 개념을 정의 못하면 트래픽이 많을때 어떻게 해결해야할지 해맨다. 쓰레드에 대한 기본 개념을 잡아보자.

클라이언트가 서버에 요청을하면 TCP/IP 커넥션이 연결이 되면서 WAS가 Servlet을 호출해준다.

그런데 이때 서블릿 객체를 누가 호출할까? 이게 중요하다.

바로 쓰레드가 서블릿 객체를 호출한다.


쓰레드

 

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

쓰레드가 하나만 있다고 가정해보자.

그러다 요청이 하나가 오면 쓰레드를 할당한다.

이 쓰레드를 가지고 서블릿을 실행해준다.

그리고 나서 쓰레드를 가지고 응답까지 다 해준다.

 

응답이 되고나면 쓰레드는 휴식한다.


이제 다중요청이 들어온다고 생각해보자.

 

먼저 요청1번이 들어와서 쓰레드를 써서 서블릿을 사용한다. 

잘 되면 좋은데 서블릿안에서 코드가 느려지거나 여러가지 요인에 의해 처리가 지연된다면?


이럴때 요청2번이 들어오면 사용할 수 있는 쓰레드가 없어서 대기하게 된다.

 

그럼 결과적으로 요청1번도 요청2번도 실패하게 된다. 

요청1번이 쓰레드를 다 쓰고 뱉어줘야 하는데, 1번이 계속 쓰고 있으니까 2번 요청이 아에 수행조차 되지 않는다.

 

그럼 기다리다가 둘다 타임아웃 나거나 하면서 오류가 발생한다.

 

이걸 해결하려면 단순한 방법이 있다. 그냥 쓰레드를 또 하나 생성하면 된다.


 

요청1이 지연되고 있어도, 이런걸 고민할 필요 없이 요청2번이 오면 새로 쓰레드를 만든다. (요청마다 쓰레드 생성)

그럼 새로 쓰레드를 만들었기 때문에 같은 서블릿을 호출해도 2번요청의 쓰레드는 2번요청의 코드를 쭉 실행한다.

 

실행이 끝나면 응답메시지 보내고 쓰레드를 날려버린다. 이렇게 개발 해도된다.

물론 개발자가 하진 않을거고 WAS가 이렇게 구현해줘도 된다. 그래도 충분히 잘 동작할 것이다.

 

 


요청 마다 쓰레드 생성 - 장단점

  • 장점
    • 동시 요청을 처리할 수 있다.
    • 리소스(CPU, 메모리)가 허용할 때 까지 처리가능
    • 하나의 쓰레드가 지연 되어도, 나머지 쓰레드는 정상 동작한다.
  • 단점
    • 쓰레드는 생성 비용은 매우 비싸다.
       • 고객의 요청이 올 때 마다 쓰레드를 생성하면, 응답 속도가 늦어진다.
    • 쓰레드는 컨텍스트 스위칭 비용이 발생한다.
    • 쓰레드 생성에 제한이 없다.
       • 고객 요청이 너무 많이 오면, CPU, 메모리 임계점을 넘어서 서버가 죽을 수 있다.

이렇게 요청이 올 때마다 쓰레드를 만들때  응답속도가 느려지고

컨텍스트 스위칭 비용이 발생한다.

- CPU가 수백개 있는게 아니고, 코어 하나가 2개를 동시에 수행할수 없는데 2개를 전환할때 발생하는 비용이 컨텍스트 스위칭 비용.

쓰레드 생성에 제한이 없는것도 단점이다. 고객요청이 너무 많으면 쓰레드가 계속 생성된다.

CPU, 메모리가 임계점을 못버티고 죽어서 서버가 다운된다. 

메모리 이미 가득 차버렸는데 계속 쓰레드 생성하려하니까 서버가 죽어버린다.

 


 

이걸 해결하기위해서 보통 WAS들은 내부에 쓰레드 풀이 있다.

거기 안에서 쓰레드들이 있다가 요청이 오면 쓰레드 풀에 요청해서 쓰레드를 받아서 쓴다.

쓰레드를 다 쓰면 쓰레드를 죽이는게 아니라 쓰레드 풀에 반납한다.

그럼 다시 쓰레드 풀의 쓰레드가 200개가 된다.

 

이런식으로 죽이고 생성하는게 아니라 미리 만들어서 풀 안에 넣어놓고 빌려쓰고 반납한다.

이렇게 하면 장점으로 200개넘는 요청 부터는 쓰레드풀의 쓰레드가 없으면 대기하거나 또는 요청 거절한다.

대기로 할지 삭제로 할지는 설정 할 수 있다.


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

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

쓰레드 풀 - 실무 팁

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

MAX 쓰레드 자체를 낮게 잡으면 생기는 문제점

 

예를들어 서버가 사양이 낮으니까 10개만 세팅할래..하고 감없이 10개만 세팅했다 가상해보자

 

이러고 서비스를 오픈했는데 대박나서 100명이 요청을 한다.

쓰레드풀에 10개가 있으니까 10개 요청은 정상처리되고 있고 90개의 요청은 대기하고있다.

 

서버가 난리가 났다. 고객이 안들어오고 응답이 지연된다고..

그래서 개발자가 CPU 상황을 보는데 5%밖에 사용 안하고 있다 (극단적인 상황이긴 함)

MAX 쓰레드를 낮게 잡으면 이런 문제가 있다. 계속 밀리면서 장애가 난다. WAS는 살아있어도 서비스 자체는 장애.

 

개발자 입장에서 CPU를 5%밖에 안쓰고 있는건 치욕적인거다. 

이건 개발자가 세팅을 잘못한거다. 나중가서 서버 증설하는건 부끄러운거다.

못해도 CPU 50%는 쓰게 해야한다. 

 

설정 하나를 잘못해서 서버를 10개 더 증설해서 쓰는건 돈만 10배로 나가는거다.

 

반대로 쓰레드풀을 너무 많이 설정한다면?

 

쓰레드풀을 10000개로 설정하면 요청이 너무 많아서 CPU, 메모리 임계점을 넘어서 서버가 죽어버린다.

이래서 적정점을 찾는게 중요하다.

 

클라우드 서버라면 일단 서버증설 후 튜닝할수 있지만 아니라면 평소에 튜닝을 잘 해놔야한다.

 


쓰레드 풀 - 쓰레드 풀의 적정 숫자

  • 적정 숫자는 어떻게 찾나요? : 아무리 잘하는 사람도 최적해를 못낸다. 감을 잡는거지.
  • 애플리케이션 로직의 복잡도, CPU, 메모리, IO 리소스 상황에 따라 모두 다름
  • 성능 테스트
    • 최대한 실제 서비스와 유사하게 성능 테스트 시도하자.
    • 툴: 아파치 ab, 제이미터, nGrinder를 사용해서 테스트 가능하다.

 

고객 트래픽이 작은 사이트는 별 상관없지만 큰 사이트는 성능테스트가 중요하다.


WAS의 멀티 쓰레드 지원 - 핵심

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

 

사실 이 글의 핵심은 WAS가 멀티 쓰레드를 지원해준단 거다.

개발자가 멀티 쓰레드 코드 짤려면 공부해야할게 진짜많고 머리 터진다.

 

WAS가 지원해줌으로 개발자는 비지니스 로직만 구현하면 된다. 

그럼 고객이 10명, 100명이 오든 멀티 쓰레드 요청은 설정만 하면된다.

 

설정만하면 풀 관리하고 이런건 WAS가 알아서 해준다. 가장 개발 생산성을 높여주는건 여기에있다. 

 

싱글톤인거 한가지만 주의하면 된다.

WAS에 여러 요청이 들어오면 공유변수만 조심하고, 이것만 챙기면 큰 걱정없이 애플리케이션 개발 가능할것이다.

반응형