1. 스레딩 모델 개요
- 스레딩 모델은 운영체제, 프로그래밍 언어, 프레임워크 또는 애플리케이션에서 스레드 관리의 핵심 측면을 지정합니다.
- 개발자는 각 모델의 트레이드오프를 이해하고 적절한 모델을 선택해야 합니다.
1.1 자바의 스레딩 발전 과정
- 초기 자바 애플리케이션에서는 매우 단순한 방식으로 스레드를 관리했습니다.
- 새로운 작업이 필요할 때마다 Thread 객체를 생성하고 시작
- 작업이 완료되면 스레드를 종료
- 필요에 따라 이 과정을 반복
- 이러한 원시적인 접근 방식은 다음과 같은 문제점을 가지고 있었습니다:
- 스레드 생성/제거의 높은 오버헤드
- 리소스 낭비
- 시스템 부하 증가
1.2 Java 5의 Executor API
- Java 5에서는 이런 문제를 해결하기 위해 Executor API가 도입되었습니다.
- 이는 스레드 풀 패턴을 구현한 것으로, 다음과 같이 작동합니다
- 풀의 free list에서 스레드를 선택
- 선택된 스레드에 제출된 작업(Runnable) 할당
- 작업 완료 후 스레드를 free list로 반환
- 스레드 재사용 가능
// 스레드 풀 생성
ExecutorService executor = Executors.newFixedThreadPool(10);
// 작업 제출
executor.submit(() -> {
// 실행할 작업
});
1.3 컨텍스트 스위칭 오버헤드
- 스레드 풀링은 개선된 방식이지만, 여전히 다음과 같은 문제가 있습니다:
- 활성 스레드 수가 증가할수록 컨텍스트 스위칭 비용 증가
- 높은 부하 상황에서 성능 저하
- 복잡한 애플리케이션에서 스레드 관련 문제 발생 가능성
2. EventLoop
- Netty의 EventLoop는 연결 수명 동안 발생하는 이벤트를 처리하는 핵심 추상화입니다.
2.1 EventLoop 동작 원리
- EventLoop의 기본 동작은 다음과 같은 무한 루프 형태입니다
예시
while (!terminated) {
List<Runnable> readyEvents = blockUntilEventsReady();
for (Runnable ev: readyEvents) {
ev.run();
}
}
- EventLoop는 다음과 같은 순서로 작업을 처리합니다:
- 이벤트가 준비될 때까지 블록
- 준비된 이벤트들을 순차적으로 실행
- 종료 신호를 받을 때까지 반복