• 티스토리 홈
starryeye
  • 프로필사진
    starryeye
    • 분류 전체보기 (189)
      • C++ (17)
      • Java (24)
      • OOP (5)
      • Spring Reactive Stack (12)
        • Reactive Streams (3)
        • Netty (4)
        • Reactor (1)
        • Webflux (3)
        • DB, Cache 연동 (1)
      • Spring (90)
        • Core (17)
        • MVC (33)
        • Client (2)
        • Security (4)
        • DB, Cache 연동 (33)
      • DataBase (12)
        • RDBMS (2)
        • NoSQL (10)
      • Message Broker (6)
      • Web (4)
      • Network (4)
      • 대규모 시스템 설계 (15)
  • 방문자 수
    • 전체:
    • 오늘:
    • 어제:
  • 최근 댓글
      등록된 댓글이 없습니다.
    • 최근 공지
        등록된 공지가 없습니다.
      # Home
      # 공지사항
      #
      # 태그
      # 검색결과
      # 방명록
      • Netty 1
        2024년 01월 17일
        • starryeye
        • 작성자
        • 2024.01.17.:11
        반응형

         

        Spring reactive stack 에서 사용되는..

        Spring webflux 는 reactor 와 netty 를 의존한다.

        뿐만 아니라, Spring data redis 도 netty 를 의존한다.

         

         

        이번 포스팅에서는 netty 를 알아보겠다.

         

        Netty 소개

        Netty 공식 홈페이지에 따르면

        "Netty is asynchronous event-driven network application framework" 라 소개한다. (Server & Client)

         

        Netty 는..

        HTTP, SMTP, FTP 등의 protocol 뿐만 아니라 다양한 protocol 을 지원한다.

        또한, 불필요한 memory copy 를 최소화 하며

        Java IO, NIO, selector 기반으로 적은 리소스로 높은 성능을 보장한다.

        (Reactor pattern 을 사용함)

        유연하고 확장가능한 Event model 을 기반으로 관심사를 명확하게 분리할 수 있다.

         

        정리

        Java NIO + Selector + (epoll) + Reactor pattern 을 사용하며

        I/O 관점에서 busy wait 을 I/O multiplexing 로 어느정도 극복하고, 동기, non-blocking 성격이 있다.

        Netty application 내부 관점에서는 이벤트 기반 비동기로 처리를 한다.

         

        이를 통해 C10K problem 을 효과적으로 대응할 수 있다고 생각한다.

         

         

        Netty 주요 구성

        NioEventLoop

        일반적으로 단일 스레드가 연속적인 루프를 돌며.. 

        I/O 네트워크 이벤트를 감지하고 처리하는 역할을 맡고있다.

         

        대표적으로 아래 개념을 가진다.

         

        EventExecutor

        이벤트(Task) 처리를 위한 스레드풀이며, 실행 상태를 확인하는 메서드를 제공한다.

        NioEventLoop 는 SingleThreadEventExecutor 를 상속한다.

        즉, single thread 로 task 처리를 하며 무한 루프를 돈다.

         

        TaskQueue

        발생되는 Task 가 저장이되면 EventLoop 가 하나씩 꺼내서 작업하는 구조를 위해 사용되는 Queue 이다.

        Task 는 I/O 이벤트(I/O task)가 될 수 도 있고 일반적인 작업(non - I/O task)일 수 도 있다.

        Task 는 비동기로 작업되어야 한다.

        저장되는 Task 는 Thread-safe 해야한다.

         

        Selector

        I/O Multiplexing 을 지원한다.

         

        NioEventLoopGroup

        Netty 의 EventLoopGroup 는 여러 개의 EventLoop 가 속하는 구조로 지원한다.

        "new NioEventLoopGroup()" 으로 생성할 경우 내부 NioEventLoop(EventExecutor) 는

        실행시킨 컴퓨터의 CPU core 개수 * 2 개가 된다.

         

        EventLoop 와 EventExecutor, EventLoopGroup 은 따로 있는 개념이 아니라 하나로 보면 편하다.

        NioEventLoop 는 사용자가 직접 생성할 수 없다.

         

        사용자는 NioEventLoopGroup 을 생성하여 사용할 수 있다.

         

         

        참고

        즉, reactive stack 에서는 I/O 처리를 위해 사용되는 스레드는 고정적임을 알 수 있다.

        그러나, servlet stack 에서도 I/O 처리를 위해 사용되는 스레드가 보통 thread pool 로 고정적으로 관리 된다.

        하지만, servlet stack 에서는 요청 당 할당으로 요청에서 blocking 이 발생하면 그 thread 는 아무 것도 못하지만..

        reactive stack 에서는 blocking 이 발생하지 않도록 하여, thread 자원을 효율적으로 사용할 수 있어서

        C10K problem 을 극복할 수 있다.

         

         

        Task(Event)

        I/O task 와 non - I/O task 로 구분된다.

         

        I/O task

        NioEventLoop 가 관리하는 selector 에 등록된 channel 에서 I/O (준비완료) 이벤트가 발생하면

        channel 의 pipline 을 실행한다.

         

        non - I/O task

        TaskQueue 에 존재하는 I/O task 가 아닌 모든 task 이다.

         

         

        ioRatio

        EventLoop 가 taskQueue 에서 I/O task 와 non - I/O task 를 꺼내서 수행할 때,

        실행 시간의 비율이다. (기본 값은 50, 1:1 이다.)

        50 이상이면, I/O task 실행시간 비율이 높은 것이다.

         

         

        NioServerSocketChannel, NioSocketChannel

        netty 의 Channel 은 Java nio 의 Channel 과 무관하다.

        EventLoop 에 여러 개의 netty 의 Channel 을 등록할 수 있다. (register 메서드)

         

         

         

        NioServerSocketChannel, NioSocketChannel 은..

        각각 Java NIO 의 ServerSocketChannel, SocketChannel 과 기본적으로는 비슷한 역할을 한다.

         

         

        중간에 보이는.. ServerSocketChannel, SocketChannel, Channel 은 Java nio 소속이 아님을 다시한번 상기하자..

         

        EventLoop 에 Channel 을 register 메서드를 통해 등록

        EventLoop 를 시작하게 만들고

        EventLoop 가 selector 를 통해 Channel 에서 발생되는 I/O 이벤트를 감지하기 시작한다.

         

        즉, 예를 들면..

        NioServerSocketChannel 의 경우 accept 가 되면(accept 체결 완료) EventLoop 는 이를 감지할 수 있다.

         

         

        ChannelPipline

        EventLoop 는 Channel 에서 발생되는 I/O 이벤트를 감지하다가 발생하면 

        해당 Channel 이 가지고 있는 ChannelPipline 을 실행한다.

        즉, ChannelPipline 은 I/O task 에 해당하는 것이다.

         

        참고

        AbstractChannel 이 ChannelPipline 을 가지고 있다.

        EventLoop 에 등록할 Channel 에 ChannelPipline 을 등록하는 방식으로 사용한다.

         

         

        ChannelPipline 은 위 그림과 같이 ChannelInboundHandler 와 ChannelOutbound Handler 의 집합으로 이루어져있다.

         

        inbound 는 보통 Channel 에서 발생된 read 이벤트를 처리하는 ChannelHandler 로 사용되며,

        outbound 는 보통 Channel 에 write 를 하기 위한 ChannelHandler 로 사용된다.

         

        EventLoop 가 selector 를 통해 이벤트를 감지하면 해당 Channel 에 등록되어있는

        ChannelInboundHandler 를 실행하는데 ChannelInboundHandler 는 여러 개의 체인 형식으로 되어있다.

        등록 순서에 따라 N 개를 순차적으로 수행한다.

         

         

        위 그림은 ChannelInboundHandler 인터페이스의 일부이다.

        원하는 이벤트를 받아 처리하려면 해당 이벤트에 맞는 메서드를 구현하고

        ChannelInboundHandler 를 Channel 에 등록하면 ChannelPipline 으로써 동작된다.

         

        참고

        각 메서드의 Object 타입의 파라미터는 이벤트 결과에 대한 객체가 들어온다고 생각하면 된다.

        NioServerSocketChannel 에서 accept 가 되면 channelRead 가 수행되는데

        이때 전달되는 Object 는 accept 결과인 NioSocketChannel 이다.

        또는, 이전 ChannelHandler 가 존재했다면 그 ChannelHandler 가 넘긴 특정 데이터일 수 있다.

         

        참고

        Inbound, outbound 외에 duplex 라는 핸들러가 있는데

        inbound 방향(next)과 outbound 방향(prev) 모두 수행되는 핸들러이다.

         

         

         

        ChannelHandlerContext

        ChannelHandler 의 메서드 파라미터로 전달되는

        ChannelHandlerContext 는 다음 ChannelHandler 로 넘기는 메서드를 제공하며

        (Spring MVC filter 에서 doFilter 를 연상해보자)

        inbound 핸들러에서 outbound 핸들러로 방향 전환할 때도 사용된다.

        Channel 로 write 할 데이터를 보낼 수도 있다.

         

        ChannelHandler 는 ChannelHandlerContext 에 의해 관리된다.

        또한, ChannelHandlerContext 에는 이전, 이후 의 ChannelHandlerContext 를 가지고 있다.

        그래서, ChannelHandlerContext 로 다음에 수행되어야 하는 ChannelHandler 로 넘길 수 있는 것이다.

         

        ChannelHandler, ChannelHandlerContext, ChannelPipline, Netty 의 Channel 의 관계는

        위 그림을 참조하면 쉽다.

         

        ChannelFuture

        위는 netty 의 ChannelFuture 설명과 코드 일부이다.

         

        netty 내부적으로 사용하는 Future 이다.

        Java Future 를 상속받아 자체적으로 ChannelFuture 라는 객체를 사용한다.

        netty 의 Channel I/O 작업이 완료되면 isDone() 을 호출 했을 때, true 를 반환한다.

        addListeners / removeListeners 등을 통해 FutureListener 를 등록하거나 삭제할 수 있다.

         

        이를 통해 EventLoop 는 내부 selector 를 통해 I/O 작업이 완료됨을 감지하면

        등록된 FutureListener 를 수행될 것임을 추론해볼 수 있다.

        사용자는 리스너를 통해 비동기로 특정 작업을 수행할 수 있는 것이다.

         

        참고

        Netty 의 ChannelHandlerContext 는 Channel{Inbound/outbound}Invoker 를 상속하는데..

        ChannelXXXInvoker 가 제공하는 대부분의 메서드 리턴 타입이 ChannelFuture 이다.

        따라서, ChannelHandlerContext 로 리스너를 등록해볼 수 도 있다.

         

         

         

         

         

         

        참고하면 좋음

        https://aws.plainenglish.io/netty-core-component-eventloop-source-code-analysis-cb7e53adc8e5

         

         

         

         

        반응형

        'Spring Reactive Stack > Netty' 카테고리의 다른 글

        Netty 2  (0) 2024.01.21
        Proactor pattern  (0) 2023.11.20
        Reactor pattern  (0) 2023.11.19
        다음글
        다음 글이 없습니다.
        이전글
        이전 글이 없습니다.
        댓글
      조회된 결과가 없습니다.
      스킨 업데이트 안내
      현재 이용하고 계신 스킨의 버전보다 더 높은 최신 버전이 감지 되었습니다. 최신버전 스킨 파일을 다운로드 받을 수 있는 페이지로 이동하시겠습니까?
      ("아니오" 를 선택할 시 30일 동안 최신 버전이 감지되어도 모달 창이 표시되지 않습니다.)
      목차
      표시할 목차가 없습니다.
        • 안녕하세요
        • 감사해요
        • 잘있어요

        티스토리툴바