Java NIO 의 Selector 와 epoll

이전 포스팅에서 selector 를 알아봤는데...

결국 selector 는...

여러 이벤트를 하나의 스레드로 한꺼번에 확인할 수 있는 객체였다. (IO Multiplexing)

 

그러면 다시 busy-wait 관점에서 생각하자면..

selector 가 도입 되면서.. busy-wait 가 사라졌을까..

아니다..

 

사용자 코드에서는 사라졌지만,

selector 가 사용자를 대신해서 준비 완료되었는지.. 확인하고 있는 것이다.

혹은... selector 로 좀더 편하게 준비 완료되었는지 확인하는 것이다..

 

좀더 설명하자면..

selector 사용 전에는 accept, read (IO 호출)를 직접 호출(사용자 코드가 Caller 입장)하였지만..

이제는 사용자 코드가 Callee 느낌으로.. selector 가 등록된 Channel 로 IO 호출을 한다.

 

 

Selector 가 제공하는 메서드를 보고 계속 하겠다.

select()

Java IO 의 accept, read 와 같이 blocking 으로.. 동작하며

준비 완료 이벤트가 있을때 리턴된다.

 

select(timeout)

select() 와 동일하게 blocking 되지만,

일정 시간이 지나도 준비 완료 이벤트가 없으면 리턴된다.

 

selectNow()

non-blocking 으로 동작하며,

준비완료된 이벤트가 없어도 리턴된다.

이 메서드를 이용하면 busy-wait 가 발생한다.

 

결론.

Selector 를 사용하면..

여러개의 스레드가 이벤트를 서로 필요한 이벤트를 busy-wait 로 확인 해야하던 구조에서..

이론상 하나의 스레드가 해당 서버에서 이루어지는 IO 이벤트를 모두 확인(동기)할 수 있게 된 것이다.

따라서, Java NIO Selector 를 사용하더라도 동기 non-blocking 이다.

 

마지막으로, 그림 구조를 한번 보자..

thread, server 는 사용자 공간으로

selector 를 이용하여 이벤트를 처리한다고 생각하면된다.

 

epoll

linux, JVM 환경 기준으로 설명하겠다.

 

epoll 은 linux 커널 내부에 존재하는 인스턴스이다.

epoll 은 커널 수준의 I/O 이벤트 알림 메커니즘으로,

사용자 공간의 애플리케이션과 커널 공간 사이에서 I/O 이벤트를 효율적으로 다루기 위해 설계되었다.

 

epoll 작동 방식

1. 인스턴스 생성

애플리케이션은 epoll_create 시스템 호출을 사용하여 epoll 인스턴스를 생성한다.

이 호출이 성공하면, 커널 내부에 epoll 인스턴스가 생성된다.

 

2. 이벤트 테이블

생성된 epoll 인스턴스는 파일 디스크립터(FD)와 이벤트를 매핑하는 내부 테이블을 유지한다.

이 테이블은 커널 공간에 위치하며,

애플리케이션은 epoll_ctl 시스템 호출을 통해 이 테이블에 파일 디스크립터를 추가, 수정 또는 제거할 수 있다.

-> selector 의 channel 등록에 해당한다고 추론 해볼 수 있다.

 

3. 이벤트 감지 및 통지

epoll_wait 호출을 통해 애플리케이션은 준비된 이벤트가 있는지 확인할 수 있다.

이때, 커널은 내부 epoll 인스턴스의 상태를 확인하고,

준비된 이벤트가 있는 파일 디스크립터의 목록을 사용자 공간으로 반환한다.

-> selector 가 주기적으로 커널의 epoll 에게 준비된 이벤트가 있는지 확인하는게 바로 이 것이다.

 

 

Selector 와 Epoll 동작 과정

1. 이벤트 발생

파일 디스크립터(예: 소켓)에서 이벤트가 발생하면, 커널은 이를 감지한다.

 

2. 이벤트 기록

커널은 이 이벤트를 내부적으로 기록하고, 관련 파일 디스크립터가 준비 상태(ready)임을 표시한다.

이벤트는 epoll 인스턴스에 연결된 이벤트 테이블에 기록된다.

 

3. 사용자 공간의 폴링

JVM 내부에서, Selector는

주기적으로 select() 메서드를 호출하여 준비 상태인 이벤트가 있는지 커널에 질의한다.

 

4. 이벤트 전달

만약 준비된 이벤트가 있으면, 커널은 이 정보를 사용자 공간으로 전달한다.

이는 Selector가 호출한 select() 메서드의 반환값을 통해 이루지는 것이다.

 

'Java' 카테고리의 다른 글

Java AIO 와 비동기 non-blocking  (0) 2023.11.19
Java NIO 의 Selector  (0) 2023.11.17
Java NIO 와 동기 non-blocking + CPU 자원  (0) 2023.11.15
Java IO 와 동기 blocking + CPU 자원  (0) 2023.11.15
Java 16 주요 변경점  (0) 2023.05.20