Search
Duplicate
📒

[Spring Netty] 04. 채널 파이프라인과 코덱 ⭐

상태
미진행
수업
Spring Netty
주제
4 more properties
참고

채널 파이프라인, 코덱

이벤트 실행

NOTE
데이터를 처리하는 입출력은 Netty가 이벤트로 관리하기 떄문에 이벤트 핸들러만 구현하면 된다.
소켓 채널 데이터 수신
1.
Netty 이벤트 루프가 채널 파이프라인에 등록된 이벤트 핸들러를 가져온다.
2.
이벤트 메서드가 구현되어 있으면 실행
3.
마지막 이벤트 핸들러에 도달할 때 까지 다음 이벤트 핸들러를 가져와 1~2 반복

채널 파이프 라인

NOTE
입력 출력을 전달할 수 있도록 파이프라이닝 한다.
채널과 이벤트 핸들러 사이의 통로 역할을 수행
채널 파이프 라인 구조

등록

bootstrap = new ServerBootstrap(); bootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .handler(new LoggingHandler(LogLevel.INFO)) .childHandler(new ChannelInitializer<SocketChannel>() { // 1 @Override protected void initChannel(SocketChannel socketChannel) throws Exception { // 2 ChannelPipeline pipeline = socketChannel.pipeline(); // 3 pipeline.addLast(new LoggingHandler(LogLevel.INFO)); // 4 pipeline.addLast(new EchoServerHandler()); // 4 } });
Java
복사
1.
childrenHandler 메소드를 통해서 설정
2.
initChannel은 클라이언트 소켓 채널이 생성될 때 호출됨
3.
Netty 내부에서 할당한 빈 채널 파이프라인 가져오기
4.
파이프라인에 이벤트 핸들러 등록

초기화 순서

@Component @RequiredArgsConstructor public class ImageNettyChannelInitializer extends ChannelInitializer<SocketChannel> { private final ImageNettyInboundHandler imageNettyInboundHandler; @Override protected void initChannel(SocketChannel ch) { ChannelPipeline pipeline = ch.pipeline(); ByteBuf delimiter = Unpooled.copiedBuffer("\n", CharsetUtil.UTF_8); int maxFrameLength = 5 * 1024 * 1024; // 5MB pipeline.addLast(new DelimiterBasedFrameDecoder(maxFrameLength, delimiter)); pipeline.addLast(imageNettyInboundHandler); } }
Java
복사
1.
클라이언트가 서버 소켓에 접속 요청
2.
해당 연결을 대응하는 클라이언트 소켓 채널 객체 생성
3.
빈 채널 파이프라인 객체 생성, 클라이언트 소켓 채널에 할당
4.
클라이언트 소켓 채널에 등록된 ChannelInitalizer객체를 가져와서 initChannel 호출
5.
클라이언트 소켓 채널에 할당되어있는 파이프라인을 가져와서 이벤트 핸들러 등록

인 바운드이벤트 핸들러

NOTE
연결 상대어떤 동작을 취했을 떄 발생하는 이벤트
채널 활성화, 데이터 수신 등
Bottom-UP 형식으로 동작하기 때문에, 가장 먼저 등록한 Handler부터 마지막에 등록한 Handler 순서로 동작
이벤트 순서
메서드
설명
channelRegistered
Channel이 EventLoop에 등록되고 입출력을 처리할 수 있으면 호출됨
channelUnregistered
Channel이 EventLoop에서 등록 해제되고 입출력을 처리할 수 없으면 호출됨
channelActive
Channel의 연결과 바인딩이 완료되어 활성화되면 호출됨
channelInactive
Channel이 활성 상태에서 벗어나 로컷 피어에 대한 연결이 해제되면 호출됨
channelReadComplete
Channel에서 읽기 작업이 완료되면 호출됨
channelRead
Channel에서 데이터를 읽을 때 호출됨
channelWritabilityChanged
Channel의 기록 가능 상태가 변경되면 호출된다.
userEventTriggered
POJO가 ChannelPipeline을 통해서 전달돼서 ChannelInboundHandler.fireUserEventTriggered()가 트리거되면 호출됨.
참고코드

아웃바운드 이벤트 핸들러

NOTE
소켓 채널에서 발생한 이벤트 중 프로그래머가 요청한 동작에 해당하는 이벤트
연결 요청, 데이터 요청, 소켓 닫기 등
Top-Down 형식으로 동작하기 떄문에, 가장 마지막에 등록한 Handler부터 가장 먼저 등록한 Handler 순서로 동작
이벤트 순서
메서드
설명
bind(ChannelHandlerContext, SocketAddress, ChannelPromise)
Channel을 로컬 주소로 바인딩 요청 시 호출됨
connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)
Channel을 원격 피어로 연결 요청 시 호출됨
disconnect(ChannelHandlerContext, ChannelPromise)
Channel을 원격 피어로부터 연결 해제 요청 시 호출됨
close(ChannelhandlerContext, ChannelPromise)
Channel을 닫는 요청 시 호출됨
deregister(ChannelHandlerContext, ChannelPromise)
Channel을 EventLoop에서 등록 해제 요청 시 호출됨
read(ChannelHandlerContext)
Channel에서 데이터를 읽기 요청 시 호출
flush(ChannelHandlerContext)
Channel을 통해 원격 피어로 큐에 있는 데이터의 플러시 요청 시 호출됨
write(ChannelHandlerContext, Object, ChannelPromise)
Channel을 통해 원격 피어로 데이터 기록 요청 시 호출됨
참고코드

이벤트 이동 경로 및 메서드 실행

NOTE
서로 다른 이벤트 메서드를 구현한 이벤트 핸들러 등록
이벤트 핸들러 등록 순서에 관계없이 이벤트 순서에 따라 실행
같은 이벤트 메서드를 구현한 이벤트 핸들러 등록
먼저 등록된, 이벤트 핸들러의 메서드만 호출되고 이벤트를 소모함
두번째 이벤트 핸들러의 메서드도 호출하고 싶으면 첫번째 이벤트 핸들러에서 ctx.fireChannelRead()같은 방법으로 직접 이벤트 발생시켜 넘겨줌
ChannelPipeline p = channel().pipeline(); p.addLast("1", new InboundReadHandler()); p.addLast("2", new InboundActiveHandler()); p.addLast("3", new OutboundWriteHandler()); p.addLast("4", new OutboundWriteHandler()); p.addLast("5", new ChannelDuplexHandler());
Java
복사
2 → 1 → 5 → 4 → 3

코덱

NOTE
인코더
전송할 데이터를 전송 프로토콜에 맞춰 변환
ChannelOutboundHandler
디코더
수신한 데이터를 전송 프로토콜에 맞춰 변환
ChannelInboundHandler