IO 병목, 어떻게 해결하지

  • 클라이언트, 서버, DB 등의 구성요소들은 네트워크 기반(HTTP, TCP 등)으로 서로 통신함
  • 서버에서 DB를 읽거나 쓰는 동안은 블로킹이 발생
  • 1만명이 동시접속하는 웹소켓 서버를 만들면 메모리 사용량만 10G
    • 메모리를 늘린다하더라도 동시에 수행되는 스레드가 많으면 컨텍스트 스위칭 비용 증가
  • 트래픽이 증가하면 두 가지 이유로 자원 효율이 떨어짐
    • IO 대기, 컨텍스트 스위칭에 따른 CPU 낭비
    • 요청마다 스레드를 할당함으로써 메모리 사용량이 높아짐
  • 자원 효율을 높이는 두 가지 방법
    • 가상 스레드나 고루틴 같은 경량 스레드 사용
    • 논블로킹 또는 비동기 IO 사용

가상 스레드로 자원 효율 높이기

  • 코드를 블로킹 IO 기반으로 작성했는데 성능을 개선할 수 있는 방법은?
    • 가상 스레드 또는 고루틴을 사용하는것
  • 가상 스레드를 경량 스레드라고 부르는 이유는 플랫폼 스레드보다 더 적은 자원(메모리 등)을 사용하기 때문
    • 스레드의 기본 스택 크기가 1MB이면
  • 톰캣처럼 요청별 스레드를 생성하는 서버에서 가상 스레드를 사용하면 더 적은 메모리로 더 많은 요청 처리 가능

논블로킹 IO로 성능 더 높이기

  • 사용자가 폭발적으로 증가하면 어느 순간 경량 스레드도 한계에 마주침
  • 이때는 논블로킹 IO 방식으로 변경해야함
    • 여기에 비동기 API를 곁들이면 덜 복잡한 코드로 높은 성능을 낼 수 있음

논블로킹 IO 동작 개요

  • 논블로킹 IO는 입출력이 끝날 때까지 스레드가 대기하지 않음
    • 읽을 데이터가 없는경우 대기없이 처리

리액터 패턴

논블로킹/비동기 IO와 성능

  • 동접수로 테스트
    • JVM 힙 메모리 1.5G를 할당했을때 논블로킹IO가 20배정도의 성능향상을 보임

언제 어떤 방법을 택할까

  • 논블로킹 IO나 가상 스레드를 적용해야할때 다음을 검토해야함
    • 문제가 있는가?
    • 문제가 있다면 네트워크 IO 관련 성능 문제인가?
    • 구현 변경이 가능한가?
  • DB나 CPU 중심적인 작업에서 발생하는 성능이슈는 위 방법으로 해결 불가능