[Spring] NIO Connector & BIO Connector

leehyunjon·2022년 6월 15일
1

Spring MVC

목록 보기
3/4

Connector

전에는 Tomcat 내부의 ServletServlet Container에 대해서 공부했었다.

이번에는 Tomcat의 Servlet Container와 클라이언트를 연결시켜주는Connector에 대해서 공부해보자.

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

Tomcat의 스레드

Connector를 공부하기 앞서 잠깐 thread에 대해서 알아보자.

Thread

스레드란 프로세스 내에서 실제로 작업을 수행하는 주체라고 하며 여러개의 스레드를 사용하는 것을 멀티 스레드라고 한다.

Thread Pool

작업을 수행할때마다 스레드를 생성하지 않고 프로그램 실행에 필요한 스레드를 미리 만들어 저장하는 곳이다.

Tomcat에는 기본적으로 Thread Pool이 생성되어있고 설정되어있다.

# application.yml (적어놓은 값은 default)
server:
  tomcat:
    threads:
      max: 200 // 생성할 수 있는 thread의 총 개수
      min-spare: 10 // 항상 활성화 되어있는(idle) thread의 개수
    max-connections: 8192 // 수립가능한 connection의 총 개수
    accept-count: 100 // 작업큐의 사이즈
    connection-timeout: 20000 // timeout 판단 기준 시간, 20초
  port: 8080 // 서버를 띄울 포트번호
Thread Pool흐름
  1. min-spare(활성화 되어 있는 스레드 수) 만큼 스레드 생성
  2. 요청이 들어오면 스레드 풀에 idle한 스레드가 있는지 확인
  3. 사용가능한 스레드가 있다면 해당 스레드 할당 후 사용완료시 반납
  4. 사용가능한 스레드가 없다면 요청은 작업 큐에 쌓인다.
  5. 작업 큐가 가득차게 되면 새 스레드를 생성한다.
    • 만약 max thread까지 스레드가 만들어지게 된다면 connection-refused 요류를 반환한다.

그만큼 Tomcat은 사용자의 요청을 처리하기 위해 스레드는 필수적인 존재이다. 이 요청을 처리하기 위해 필요한 Connector에도 스레드가 사용되는데, 이 스레드를 효율적으로 처리한다면 한번에 많은 사용자의 요청을 처리할수 있게 된다.

Connector의 역할

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

Connector는 기본적으로 클라이언트의 요청을 받아 Servlet이 처리할 수 있는 HttpServletRequest로 바꿔주는 역할을 한다.

  1. 클라이언트의 요청(socket)을 얻는다.
  2. socket으로부터 socket connection을 통해 요청 데이터 패킷을 얻는다.
  3. 데이터 패킷을 파싱해서 HttpServletRequest로 캡슐화한다.
  4. 해당 HttpServletRequest를 ServletContainer로 보내 적절한 Servlet에 요청한다.

BIO Connector와 NIO Connector

위에서 설명한 Connector는 2가지 방법의 Connector가 있다. Blocking IO방법인 BIO Connector와 NonBlocking IO방법인 NIO Connector가 있다.

BIO Connector는 요청시 하나의 thread가 할당되어 요청을 처리한다. 하지만 connection이 닫힐때 까지 하나의 thread는 특정 connection에 할당되어 있기 때문에 idle(아무것도 하지 않는) 상태로 낭비되는 시간이 많아져 효율적으로 자원을 사용하지 못하게된다.

이를 해결하기 위해 NIO Connector가 등장하게 되었다.


BIO Connector

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

BIO Connector 구성요소

  • Http11Protocol
    • JIoEndPoint
      • Acceptor
      • Worker
    • Http11ConnectorHandler
      • Http11Processor
  • Mapper
  • CoyoteAdapter

Acceptor

JIoEndPoint의 Acceptor는 클라이언트 요청이 들어왔을때 port listener를 통해 소켓을 얻는다.

Worker

JIoEndPoint의 Worker는 Acceptor에서 socket을 받아서 Http11ConnectionHandler에서 Http11Processor를 얻고 요청을 처리한다.

Mapper

HttpRequest에 맞는 서블릿을 바인딩 하는데 사용.

CoyoteAdapter

Http11Processor에 의해 호출되며 worker스레드가 할당된 소켓의 Http요청을 HttpServletRequest object로 변환하는 역할을 한다.

BIO Connector 요청 처리

  1. 클라이언트 요청시 Acceptor가 port listener를 통해 소켓을 얻는다.
  2. 해당 소켓을 worker thread poold에서 idle한 worker thread를 할당 받는다.
  3. worker thread는 Http11ConnectionHandler에서 Http11Processor object을 받는다.
  4. Http11Processor object에서 CoyoteAdapter를 통해 http요청을 HttpServletRequest로 변환한다.
  5. 요청에 맞는 Servlet 호출.

						출처 : https://hadev.tistory.com/m/28

BIO Connector에서 요청이 들어오면 요청 당 하나의 thread가 할당되게 된다.
이렇게 되면 connection이 닫힐 때 까지 하나의 thread는 idle한 상태로 유지되어 다른 요청시 해당 thread는 사용할수 없어 낭비되는 시간이 많아지게 된다.


NIO Connector

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

NIO Connector 구성요소

  • Http11NioProtocol
    • NIoEndPoint
      • Acceptor
      • Poller
      • Worker
    • Http11ConnectionHandler
      • Http11NioProcessor
  • Mapper
  • CoyoteAdapter

NIoEndPoint

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

NIoEndPoint는 Http11Protocol에서 소켓을 얻고 요청을 처리하는 중요한 모듈이다.

NIoEndPoint에는 Acceptor, Poller, Worker라는 요소들이 있다.

Acceptor

NIoEndPoint의 Acceptor는 while문을 돌면서 port listener를 통해 Socket Connection을 얻게된다.

accept한 Socket Connection을 NioChannel object로 캡슐화 한 다음, NioChannel객체를 PollerEvent object로 한번 더 캡슐화한다.

PollerEvent객체는 Poller Event큐에 저장되게 된다.

Poller

Poller Event큐에 저장된 PollerEvent객체는 Poller라는 하나의 스레드를 통해 Poller에서 유지되는 Selector에 PollerEvent의 NioChannel을 등록한다.

		출처 : https://velog.io/@sihyung92/how-does-springboot-handle-multiple-requests

Poller는 NIO의 Selector를 가지고 있다. Selector에는 다수의 채널이 등록되어 있고, Poller는 select동작을 수행하여 데이터를 읽을 수 있는 소켓을 얻는다.

Selector에 등록된 NioChannel 중 데이터 처리를 할 수 있는 NioChannel의 소켓을 Worker Thread Pool에서 사용할수 있는 Worker 스레드를 가져와 처리 가능한 소켓을 worker 스레드에 할당시킨다.

Poller는 NIO구현에 있어서 주요한 스레드이다. socket이 들어오면 바로 worker 스레드를 할당시켜주는 BIO Connector와 달리 Selector에 등록해두었다가 데이터 처리가 가능한 소켓을 별도로 worker 스레드에 할당시켜 줌으로써 좀 더 효율적으로 스레드를 사용 할수 있게 된다.

Worker

Worker스레드가 Poller에 의해 소켓을 넘겨 받게 되면 socket을 SocketProcessor object로 캡슐화한다.

그리고 Http11ConnectionHandler에서 Http11NioProcessor객체를 꺼내고Http11NioProcessor객체에서 CoyoteAdapter를 호출한다.

Worker스레드 내부에서는 소켓에서 http요청을 읽고 CoyoteAdapter를 통해 HttpServletRequest로 변경한다.

HttpServletRequest를 통해 해당 서블릿에 전달하고 소켓을 통해 응답을 다시 클라이언트에게 보낸다.

						출처 : https://hadev.tistory.com/m/28

Poller와 Selector를 사용하여 각 channel을 처리하고 스레드를 할당하기 때문에 고정된 개수의 스레드로 증가하는 유저 커넥션을 핸들링 할 수 있게 되었다.
즉, 커넥션과 스레드가 1대1 매핑이 아니기 때문에 스레드 개수 이상 커넥션을 유지할수 있게 되었다.

참고로 BIO Connector는 톰캣 9.0버전 부터 삭제되었다.


Reference

https://velog.io/@sihyung92/how-does-springboot-handle-multiple-requests

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

https://blog.actorsfit.com/a?ID=00500-fff6744c-2f08-436f-a448-90b8a9105166

https://velog.io/@sihyung92/how-does-springboot-handle-multiple-requests

https://hadev.tistory.com/m/28

profile
내 꿈은 좋은 개발자

0개의 댓글