Synchronous Programming vs Reactive Programming
동기(주로 명령형 프로그래밍)에서는 각 요청마다 별도의 스레드를 할당(thread per request)하여 요청을 처리한다. 이 방법에서는 스레드 풀(Tomcat: 200 thread pool)이 모두 사용되고 있을 때와 같이 스레드가 차단되고 있을 때 요청을 처리하지 못 하여 작업이 쌓여 idle 상태가 된다. 이렇게 요청이 많은 서비스(예) 광고 서비스)에서는 idle 상태가 길게 유지되면 매우 비효율적이라고 볼 수 있다.
-
idle 상태란?
간단하게 요청의 처리를 대기하고 있는 상태라고 생각하면 된다. (휴식 같은 느낌~)
-
명령형(동기) 특징
thread per request (요청당 스레드)
요청이 동기적으로 처리되고 블로킹된다.
-
간단한 동기/블로킹 예시 하나의 활주로에서 P2는 P1이 착륙을 완료한 후에 P2가 착륙할 수 있다.
여기서 P2는 P1이 착륙을 하는 과정동안 착륙을 하지 못 한다. ( 블로킹 / 동기(순차적 실행) )
스레드가 할당되면 해당 스레드는 작업이 완료(종료)될 때까지 블로킹 상태가 된다.
스레드 풀의 크기 만큼만 요청을 처리할 수 있다.
모든 스레드가 사용 중이면 메모리 사용률이 높아져 성능 저하가 발생한다.
→ 자원 사용이 효율적이지 못 하다.
CPU에 비해 많은 스레드를 사용하는 애플리케이션은 비효율적
-
컨텍스트 스위칭으로 인한 스레드 전환 비용 발생
- 컨텍스트 스위칭 - 여러 프로세스 / 스레드가 번갈아가며 실행되는 것
- 프로세스 1을 실행 후 잠시 중단되면 PCB에 실행 정보가 저장된다.
- 프로세스 2는 프로세스 1 실행 동안 idle 상태이고, 프로세스 2의 idle 상태가 끝나면 PCB에서 실행 정보를 리로드한다.
- 그동안 프로세스 1은 당연히 idle 상태일 것이다
- 여기서 프로세스 1이 중지 되는 시점과 프로세스 2의 idle 상태가 끝나는 시점이 다르다.
- 왜? PCB에 저장하고 로드하는데 시간이 걸려 두 개의 시점이 맞지 않는 것이다.
- 그럼 CPU는 그동안 일을 못 함
- 이와 같이 스레드에서도 컨텍스트 스위칭 비용이 발생한다.
스레드가 증가할 수록 컨텍스트 스위칭 비용이 증가한다.
- 컨텍스트 스위칭 - 여러 프로세스 / 스레드가 번갈아가며 실행되는 것
-
메모리 사용에 의해 오버 헤드 발생 (스레드 증가)
- 64 비트 JVM의 default stack size는 1024KB 이다
- 하지만 50,000명이 동시에 접속할 시 50GB의 메모리가 추가로 필요하다. (오버 헤드)
-
스레드 풀의 응답 지연 문제 발생
- idle 상태의 스레드가 존재하지 않으면 응답시간이 길어짐
- 스레드 사용 후 반납 과정에서도 응답 지연이 발생한다.
-
그래도 엄청 큰 규모(트래픽)가 아닌 이상 동기식이여도 상관없다.
이러한 많은 요청(높은 트래픽)을 서버에서 빠르게 응답하고 반응하기 위해 존재하는 프로그래밍 패러다임이 반응형 프로그래밍(Reactive Programming)이다.
- 반응형 프로그래밍 특징
- 비동기 / 논 블로킹
- 배압(백프레셔) 지원
- 데이터 스트림
- 작업 스레드 사용 여부와 상관없이 차단되지 않음
- 적은 스레드 사용으로 전환 비용이 적음
- 주로 선언형 프로그래밍