Java NIO(New I/O)의 ServerSocketChannel과 SocketChannel은 블로킹과 논블로킹 방식을 지원합니다.
논블로킹 방식의 특징은 "제어권을 넘기지 않는다"라고 표현할 수 있겠습니다. 논블로킹 방식은 제어권을 넘기지 않기 때문에 함수 실행 흐름이 그대로 유지됩니다.
ServerSocketChannel의 accept() 메소드를 예시로 살펴보겠습니다. serverSocketChannel의 accept() 메소드를 실행해도 논블로킹 방식이기 때문에 결과가 바로 리턴됩니다. 따라서 언젠가는 연결 요청이 올 것을 대비해서 무한 루프 내부에서 연결을 기다려야합니다.
while(true) {
SocketChannel socketChannel = serverSocketChannel.accpet();
...
}
무한 루프 내부에서 대기하는 방식은 CPU에 부담이 될 수 있습니다. 그렇기 때문에 이를 셀렉터(Selector)를 통해서 극복할 수 있습니다. 셀렉터는 이벤트 리스너의 역할을 수행하는데, 예를 들어 클라이언트의 연결 요청이 들어오면 채널은 셀렉터에 이를 통보하고 셀렉터는 해당 채널들의 논블로킹 메소드를 수행하여 작업을 처리하도록 합니다.
원래는 다중 연결을 처리하기 위해서 아래 그림처럼 스레드 풀에 많은 스레드가 대기해야 했다면 (스레드 낭비)
지금은 셀렉터 하나와 작업을 처리할 소수의 스레드 만으로도 효율적으로 작업을 처리할 수 있는 구조가 된 것입니다.
즉 셀렉터는 멀티 작업을 싱글 스레드에서 처리할 수 있도록 해주는 멀티플렉서 역할을 하는 것입니다. (이러한 구조는 현재 톰캣의 NIO Connector에서도 살펴볼 수 있습니다)
셀렉터가 동작하는 과정은 아래와 같습니다.
- 먼저 채널을 셀렉터에 등록해야 합니다. 등록하면 셀렉터의 "관심 키셋"에 저장됩니다.
- 클라이언트의 요청이 오면 셀렉터는 "관심 키셋"에 등록된 키 중에서 작업 준비가 된 키를 "선택된 키셋"에 별도로 저장합니다.
- 작업 스레드는 "선택된 키셋"에 있는 키를 하나씩 꺼내서 키와 연관된 채널 작업을 처리합니다.
- 2~3 과정을 반복합니다.
채널을 셀렉터에 등록할 때 채널이 수행할 작업 유형을 설정할 수 있습니다.
SelectionKey의 상수 | 설명 |
OP_ACCEPT | ServerSocketChannel의 연결 수락 작업 |
OP_CONNECT | SocketChannel의 서버 연결 작업 |
OP_READ | SocketChannel의 데이터 읽기 작업 |
OP_WRITE | SocketChannel의 데이터 쓰기 작업 |
SocketChannel의 경우 여러 작업이 가능하기 때문에 작업 유형을 수정하는 것도 가능합니다.
아래는 채널의 작업 유형을 수정하는 예제입니다.
// 채널을 생성하고 논블로킹으로 설정한다
SocketChannel channel = SocketChannel.open();
channel.configureBlocking(false);
// selector를 생성하고 채널을 등록한다
Selector selector = Selector.open();
channel.register(selector, SelectionKey.OP_CONNECT);
// key를 얻는다
SelectionKey key = channel.keyFor(selector);
// 작업 유형을 변경한다
key.interestOps(SelectionKey.OP_READ);
// selector의 블로킹 상태 해제
selector.wakeup();
// 다시 selector 실행
selector.select(); // 최소한 하나의 채널이 작업 처리 준비가 될 때까지 블로킹된다.
추후 셀렉터를 이용하여 멀티 채팅 프로그램을 만들어 볼 예정입니다.
'JAVA' 카테고리의 다른 글
java for, for-each, forEach 성능 비교, 장단점, 특징 정리 (0) | 2022.10.26 |
---|---|
예외 처리와 SQLException (0) | 2022.10.24 |
[기본 시리즈] java.nio 버퍼 (1) | 2022.09.19 |
[기본 시리즈] JAVA 스레드에 대하여 (0) | 2022.09.08 |
[기본 시리즈] java.io 자바 기본 네트워킹 TCP/IP (0) | 2022.09.06 |