ChannelGroup과 GlobalEventExecutor
ChannelGroup 생성 시 왜 GlobalEventExecutor 를 사용하는지, GlobalEventExecutor 가 어떤건지 여쭤보셨습니다.
GlobalEventExecutor 가 단일 스레드 싱글톤 EventExecutor라는 내용은 알고 있었지만 어떻게 동작하는지는 알고 있지 않아서 이에 대해 알아보고자 합니다.
ChannelGroup
우선 ChannelGroup은 채널을 저장할 수 있으며, Channel이 닫히면 ChannelGroup 컬렉션에서도 자동으로 제거되는 Netty 제공 인터페이스입니다. 여러 Channel을 그룹화하여 관리하는 인터페이스라고 볼 수 있습니다.
ChannelGroup 은 스레드 안전하며, 하나의 channel은 여러 ChannelGroup에 속할 수 있고, 소속된 채널들에게 메세지를 브로드캐스트하는 경우 writeAndFlush() 메서드를 이용하여 편하게 사용할 수 있습니다.
아래와 같이 사용할 수 있다고 Netty공식문서에 나와있습니다.
ChannelGroup allChannels =
new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
DefaultChannelGroup : ChannelGroup 의 기본 구현체입니다.
ChannelGroup 의 생성자는 다음과 같습니다. ChannelGroup 을 초기화 할 때 EventExecutor를 넘겨주어야 합니다
/**
* Creates a new group with a generated name and the provided {@link EventExecutor} to notify the
* {@link ChannelGroupFuture}s.
*/
public DefaultChannelGroup(EventExecutor executor) {
this(executor, false);
}
EventExecutor 란?
EventExecutor는 Netty에서 비동기 작업을 실행하고 관리하는 인터페이스로, 스레드 풀을 사용하여 작업을 분산 처리합니다.
작업 큐를 관리하고 큐에 있는 작업을 스레드를 사용하여 실행하는 역할을 수행합니다.
기능 : 이벤트 핸들링, 타이머 작업 스케줄링, 비동기 작업 실행 등…
Netty가 제공하는 EventExecutor 종류 :
- SingleThreadEventExecutor : 단일 스레드로 동작하는 EventExecutor
- MultithreadEventExecutorGroup : 다중 스레드로 동작하는 EventExecutorGroup NioEventLoopGroup의 조상 입니다.
- DefaultEventExecutorGroup : 기본적으로 제공되는 다중 스레드 EventExecutorGroup
GlobalEventExecutor 알아보기
GlobalEventExecutor.INSTANCE : Netty에서 전역적으로 사용되는 단일 스레드 싱글톤 ‘EventExecutor’ 인스턴스입니다. 이를 통해 전역 이벤트 실행 환경을 공유할 수 있습니다.
GlobalEventExecutor 는 Netty가 초기화될 때 자동으로 생성되기 때문에, Netty 라이브러리를 사용할 때 항상 존재합니다. 그리고 특정 설정 없이도 사용할 수 있습니다.
만약 작업이 복잡한 경우에는 GlobalEventExecutor 대신 다음과 같이 다중 스레드를 사용할 수 도 있습니다.
import io.netty.channel.DefaultEventLoopGroup;
import io.netty.util.concurrent.EventExecutorGroup;
EventExecutorGroup customExecutorGroup = new DefaultEventLoopGroup(4); // 4개의 스레드로 구성된 그룹
ChannelGroup allChannels = new DefaultChannelGroup(customExecutorGroup.next());