본문 바로가기
netty

2. EventLoopGroup

by 이석준석이 2021. 4. 10.

1. EventLoopGroup Interface (io.netty.channel)

 

  • netty 에는 EventLoopGroup 이라는 인터페이스가 있으며 EventGroup 은 여러개의 EventLoop를 갖고있는 풀방식을 취합니다.


이 중에서, nio을 처리하는 NioEventLoopGroup 을 이용해서 간단한 예제를 구현해보겠습니다.

@Slf4j
public class EventLoopGroupStudy {
    public static void main(String[] args) {
        EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
        for(int i = 0 ; i < 100 ; i++) {
            int x = i;
            eventLoopGroup.next().execute(() -> log.info("execute loopGroup {}", x));
        }
    }
}
22:04:21.753 [nioEventLoopGroup-2-10] INFO EventLoopGroupStudy - execute loopGroup 9
22:04:21.753 [nioEventLoopGroup-2-10] INFO EventLoopGroupStudy - execute loopGroup 33
22:04:21.753 [nioEventLoopGroup-2-10] INFO EventLoopGroupStudy - execute loopGroup 57
22:04:21.754 [nioEventLoopGroup-2-10] INFO EventLoopGroupStudy - execute loopGroup 81
22:04:21.755 [nioEventLoopGroup-2-9] INFO  EventLoopGroupStudy - execute loopGroup 8
22:04:21.755 [nioEventLoopGroup-2-9] INFO  EventLoopGroupStudy - execute loopGroup 32....

 

비동기적인 프로그래밍을 한 것처럼, 해당 결과는 뒤죽박죽의 순서로 결과가 찍힙니다.

  • 이는 EventLoopGroup 에서 하나의 Runnable task 를 수행하면 EventLoop에 할당한 뒤에 수행을 맡기기 때문입니다. (새로운 쓰레드에 위임하는 방식과 같습니다.)

 

 

NioEventLoopGroup NioServerSocketChannel 을 갖고있으며 맨 앞단에서 Selector 과 비슷한 역할을 합니다. 

  • ※ 내부적으로 EventLoop가 Selector를 사용합니다.
  • ※ NioServerSocketChannel 은 java 의 ServerSocketChannel 과 유사하며, 비동기적으로 처리하는 netty 에서 제공하는 클래스입니다.


코드로보면 아래와 같습니다.

  • ChannelFuture 은 비동기적인 결과를 받는 Java의 Future 과 유사한 기능을합니다.
  • 아래의 코드에서는 bind 에 대한 결과를 받아 정상적으로 수행됐다면 bind Completed 메세지가 출력됩니다.
  • 해당 코드는 종료되지않고 연결을 기다리고있습니다.
@Slf4j
public class EventLoopGroupStudy {

    public static void main(String[] args) {
        EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
        final NioServerSocketChannel channel = new NioServerSocketChannel();
        eventLoopGroup.register(channel);

        final ChannelFuture bind = channel.bind(new InetSocketAddress(8080));
        bind.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
                log.info("bind completed : {}", future);
            }
        });
    }
}
bind completed : [id: 0x729bde16, L:/0:0:0:0:0:0:0:0:8080]

위의 결과에서 보다시피, ChannelFuture 에는 바인딩된 정보가 들어있고, 이를 통해 연결된 채널의 정보를 가져올 수 있습니다. (여기서는 NioServerSocketChannel 을 연결했으므로 NioServerSocketChannel 이겠죠)


2. PipeLine

 

channel 에는 pipeLine 을 추가할 수 있습니다.

  • channel 에 어떤 데이터가 왔을때 어떻게 수행하라고 명시할 수 있습니다.
  • pipeline 에는 여러개의 Handler를 추가할 수 있으며, 순차적으로 진행됩니다.
    • ChannelInboundHandler, ChannelOutBoundHandler 를 공부해보세요!


ChannelInboundHandlerAdapter 를 통해서 channelRead 이벤트가 발생하는 경우 출력해보는 코드를 작성해보겠습니다.

  • 코드가 많이 헷갈릴 수 있으나
    • operationComplete(ChannelFuture future) -> 바인드가 성공한 경우
    • future.channel().pipeline().addLast(ChannelHandler...) -> 바인드가 성공한 채널파이프라인핸들러를 등록한다.
@Slf4j
public class EventLoopGroupStudy {

    public static void main(String[] args) {
        EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
        final NioServerSocketChannel channel = new NioServerSocketChannel();
        eventLoopGroup.register(channel);

        final ChannelFuture bind = channel.bind(new InetSocketAddress(8080));
        bind.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
                log.info("{}", future.channel());
                future.channel().pipeline()
                    .addLast(new ChannelInboundHandlerAdapter(){
                        @Override
                        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                            final Channel channel = (Channel) msg;
                            log.info("channel : {}", channel);
                            super.channelRead(ctx, msg);
                        }
                    });
            }
        });
    }
}

 

위의 코드를 수행한뒤에 1. Java Channel 에서 만든 클라이언트로 연결을 시도하면 아래와같이 출력됩니다.

  • 8181 포트의 클라이언트가 8080 쪽으로 정상적으로 연결됐습니다.
  • EventLoop 가 로그를 출력하였으므로, 응답을 보내거나 하는 부분은 EventLoop 가 도맡아 수행하게되며, 비동기적으로 수행하게됩니다.
  • EventLoop 에 등록된 NioSocketChannel은 해당 EventLoop 가 도맡아 끝까지 처리합니다.
22:55:39.501 [nioEventLoopGroup-2-1] INFO EventLoopGroupStudy - channel : [id: 0xa3ed8d0c, L:/127.0.0.1:8080 - R:/127.0.0.1:8181]

 

 

'netty' 카테고리의 다른 글

3. BootStrap  (0) 2021.04.13
1. Java Channel  (0) 2021.04.10