brunch

You can make anything
by writing

C.S.Lewis

by myner Oct 18. 2020

네티 NioEventLoopGroup

feat. 스레드 풀

NioEventLoopGroup

NioEventLoopGroup 객체는 내부적으로 스레드 그룹을 유지하는 스레드 풀로 이해할 수 있다. 


각 스레드는 여러 채널에서 이벤트를 처리하고 채널은 하나의 스레드에만 해당하므로 여러 스레드에서 데이터 동기화 문제를 피할 수 있다.


Reactor 스레드 모델

세 가지 Reactor 스레딩 모델이 있다.  

단일 스레드 모델

다중 스레드 모델

마스터-슬레이브 Reactor 스레딩 모델


NioEventLoopGroup과 Reactor 스레드 모델 간의 대응

NIOEventLoopGroup은 Reactor와 어떤 관련이?? 실제로 NIOEventLoopGroup은 스레드 풀 구현으로, 서로 다른 NIOEventLoopGroup 메서드를 설정하여 세 가지 Reactor 스레드 모델에 대응할 수 있다.


단일 스레드 모델


EventLoopGroup bossGroup = new NioEventLoopGroup(1); 

ServerBootstrap b = new ServerBootstrap(); 

b.group(bossGroup).channel(NioServerSocketChannel.class); 

.

@Override public ServerBootstrap group(EventLoopGroup group) {    

     return group(group, group); 

}


다중 스레드 모델


EventLoopGroup bossGroup = new NioEventLoopGroup(1); 

EventLoopGroup workerGroup = new NioEventLoopGroup(); 

ServerBootstrap b = new ServerBootstrap(); 

b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class);


bossGroup에는 스레드가 하나뿐이다. workerGroup 스레드 풀에 스레드 수를 지정하지 않았으므로 기본값은 CPU 코어 수에 2를 곱한 것이므로 Reactor 스레드 모델에 해당하므로 이러한 방식으로 설정된다.  



마스터-슬레이브 스레딩 모델


EventLoopGroup bossGroup = new NioEventLoopGroup(4); 

EventLoopGroup workerGroup = new NioEventLoopGroup(); 

ServerBootstrap b = new ServerBootstrap(); 

b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class); 


Netty의 서버 측  Acceptor 단계는 멀티 스레딩을 사용하지 않으므로 위의 마스터-슬레이브 멀티 스레딩 모델은 Netty의 서버 측에 존재하지 않는다.


서버 측의 ServerSocketChannel은 bossGroup의 하나의 스레드에만 바인딩되므로 Java NIO Selector.select를 호출하여 클라이언트 연결 요청을 처리 할 때 실제로 하나의 스레드만 사용되므로 서비스가 하나만있는 애플리케이션의 경우 bossGroup 설정 다중 스레드는 효과가 없지만 자원 낭비를 유발한다.


Google에 따르면 Netty의 bossGroup이 스레드 풀을 사용하는 이유는 다양하지만 stackoverflow 에서 더 신뢰할 수있는 답변 을 찾았다.

Netty의 제작자는 NioEventLoopGroup을 서로 다른 서버 부트 스트랩간에 공유하는 경우 여러 보스 스레드가 유용하다고 말했지만 그 이유는 모르겠다.


NioEventLoopGroup의 핵심 클래스 상속 관계는 다음과 같다.

NioEventLoopGroup – "MultithreadEventLoopGroup –"MultithreadEventExecutorGroup

이전 BootStrap 글에서 잠깐 다루었다.


NioEventLoopGroup 인스턴스화 프로세스

이전 BootStrap Netty 소스 코드 분석 중  NioEventLoopGroup의 초기화 프로세스를 간략하게 소개했다. 


정리

1. EventLoopGroup (실제로 MultithreadEventExecutorGroup)은 스레드 풀을 구성하는 크기가 nThreads 인 EventExecutor 자식 유형의 배열을 내부적으로 유지한다.


2. NioEventLoopGroup을 인스턴스화하는 경우 스레드 풀 크기가 지정되면 nThreads가 지정된 값이고 그렇지 않으면 프로세서 코어 수 * 2이다.  


3. MultithreadEventExecutorGroup은 newChild 추상 메서드를 호출하여 자식 배열을 초기화한다.  


4. 추상 메서드 newChild는 NioEventLoop 인스턴스를 반환하는 NioEventLoopGroup에서 구현된다.  


결론

NioEventLoopGroup은 실제로 스레드 풀이다. 

NioEventLoopGroup은 백그라운드에서 n NioEventLoop을 시작하여 채널 이벤트를 처리한다.

각 NioEventLoop은 m 개의 채널을 처리한다.

NioEventLoopGroup은 NioEventLoop 배열에서 NioEventLoop을 하나씩 가져와 채널을 처리한다.



https://segmentfault.com/a/1190000007282789 

https://www.slideshare.net/kslisenko/networking-in-java-with-nio-and-netty-76583794 

https://www.slideshare.net/JangHoon1/netty-92835335?from_action=save

https://blog.csdn.net/zxhoo/article/details/17419229 

https://slowdev.tistory.com/16 

https://sina-bro.tistory.com/15 

https://github.com/YonghoChoi/develop-note/blob/master/md/Netty/3장_부트스트랩.md 

https://blog.csdn.net/zxhoo/article/details/17532857 

https://clairdelunes.tistory.com/26 

https://runningup.tistory.com/entry/부트스트랩-1 

https://juyoung-1008.tistory.com/23

브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari