아파치 톰캣의 NIO Connector 와 BIO Connector에 대해 알아보자.

최지환·2022년 8월 19일
3

스프링

목록 보기
8/12
post-thumbnail

글을 쓰게 된 계기

스터디에서 스프링 MVC 를 공부하면서, Servlet과 Servlet 컨테이너에 대해 설명한 적이 있다.

이때 내가 톰캣은 쓰레드 풀 방식으로 Http 요청을 처리한다고 하는 과정을 설명하였다. 이때 쓰레드 풀에 사용 되는 쓰레드의 갯수는 최대 200 개라고 했었다.

관련 내용

WAS의 서블릿 객체를 호출하는 쓰레드

그후 “그렇다면 Http 연결과 응답에 대한 처리를 하는 쓰레드는 쓰레드 풀 안에 있는 쓰레드인가?” 라는 질문을 받았고, 이에 대해 제대로 답변을 하지 못했다.

따라서 좀 더 공부를 해보았고, 이 글을 쓰게 되었다.


Connector

Servlet Container와 클라이언트를 연결시켜준다.

톰캣으로 첫 요청이 들어오는 곳이다.
Connector 은 클라이언트의 요청을 받아 이를 토대로 Servlet이 처리 할 수 있는 HttpServletRequest를 생성한다.

BIO Connector와 NIO Connector

Connector는 2가지 종류의 Connector이 있다.

Blocking IO 방식인 BIO Connector 와 None-Blocking 방식인 NIO Connector이 있다.

NIO(New Input Output)

자바 4 부터 새롭게 추가된 입출력 방식(New Input Output)이다. 이후 자바 7에 버전 업데이트가 되어 자바 IO 와 NIO 사이의 일관성이 없던 클래스 설계를 바로 잡고 네트워크 지원(비동기 채널 등)기능이 강화되어 NIO2가 추가됨

IONIO
입출력 방식스트림 방식채널 방식
버퍼 방식넌버퍼버퍼
비동기 방식지원 안함지원
블로킹/넌블로킹 유무블로킹 방식만 지원블로킹 / 넌블로킹 방식 모두 가능

스트림과 채널의 차이

  • 스트림은 입력 스트림과 출력 스트림이 구분되어 있음
    데이터를 읽기 위해서는 입력 스트림을 통해 읽어야하고, 출력을 위해서는 출력 스트림을 사용해야함
  • 채널은 양방향 입출력 가능
    입력과 출력을 위한 별도의 채널이 필요하지 않음

None Buffer 와 Buffer 의 차이

None Buffer(IO) 는 대체로 느림

  • 1 바이트 정보를 입력받고 출력 할때, 입력 스트림에서 1 바이트를 쓰고 출력 스트림에서 1 바이트를 써야함
  • 따라서 버퍼를 제공해주는 보조 스트림(구현체)인 BufferedInputStream, BufferedOutputStream을 연결해서 사용

NIO는 버퍼를 사용하여 입출력하기 때문에 IO 보다 성능이 좋음

  • 채널은 입력된 데이터를 버퍼에 저장하고, 저장되어 있던 데이터를 출력함

블로킹과 넌 블로킹의 차이

IO ( 블로킹 방식)

  • 입력 스트림의 read() 를 호출하면 데이터가 입력 될 때 까지 스레드는 대기상태를 유지하고,
    출력 스트림의 write()를 호출할 경우 데이터 출력을 할 때 까지 스레드는 대기 상태를 유지함.
  • 따라서 이런 대기상태(블로킹)일 때마다 스레드는 다른 일을 할 수 없고, 인터럽트(블로킹을 빠져나오기 위해)를 할 수 없음 → 빠져나오기 위해서는 강제로 스트림을 닫아야함

NIO ( 넌 블로킹 방식 + 블로킹 방식)

  • NIO는 블로킹 방식 넌 블로킹 방식 둘다 지원
  • 스레드 인터럽트 가능
  • 핵심 구현체는 멀티플렉서인 셀렉터(Selector)이다. → 복수 개의 채널 중에서 준비 완료된 채널을 선택하는 방법 제공

동기 비동기에 대한 차이 비교

💡 요약 : NIO는 불특정 다수의 클라이언트 연결을 넌블로킹이나 비동기 처리가 가능하다 → 과도한 쓰레드 생성을 막을 수 있다.

이런 NIO 방식의 장점 때문에, 현재 톰 캣은 NIO 방식을 이용한 NIO Connector 을 사용하고 있다.

출처 https://velog.io/@jihoson94/BIO-NIO-Connector-in-Tomcat

BIO와 NIO 방식 비교

BIO 방식은 한 번의 커넥션 당 하나의 worker 쓰레드가 생성되고 이를 처리한다.

하지만 NIO 방식은 하나의 worker 쓰레드가 다중 연결을 처리할 수 있다.

NIO는 하나의 쓰레드가 다중연결을 처리 할 수 있고, 이는 Http의 KeppAlive( 같은 위치로 부터 요청이 들어올 때마다 쓰리 핸드 쉐이크를 다시 하는 것이 아닌 포트를 열어두는 방식)방식을 컨트롤 할 수 있기 때문에 현재 톰캣에서 주로 쓰인다.


NIO Connector 흐름 정리

  1. 브라우저로 부터 요청을 받는다. 이는 다중 요청일 수도 있고, 단일 요청일 수도 있다.
  2. 서버 소켓으로 요청이 입력되면 Acceptor Thread 가 요청을 받고 이를 Acceptor Queue(버퍼)에 적재한다.
  3. 커넥터 프로그램이 큐에서 Poll 해와 이를 worker Thread에게 할당한다.

결론

톰캣에서는 NIO Connector를 사용하기 때문에 동시 요청을 넌 블로킹 방식으로 처리할 수 있다.
또한 Http 요청만을 처리하는 쓰레드는 쓰레드 풀에 있는 쓰레드가 아닌 Acceptor Thread가 따로 있다.

0개의 댓글