18. New Non-blocking I/O – Illustrated
균등
Boss Thread Worker Thread #1
분배
ServerSocket- Selector.select()
Channel.accept() for each selected channels:
SocketChannel.register() SocketChannel.read()
SocketChannel.write()
Worker Thread #2
Worker Thread #3
Worker Thread #4
Worker Thread #N (# of CPU cores)
19. New Non-blocking I/O – Illustrated
Worker Thread Event Handler
onInit:
SocketChannel.read()
환영 전문 작성
SocketChannel.write()
WorkerThread.writeAsync()
현재 상태 = 인증 대기
onData:
switch ( 현재 상태 ):
인증 대기 :
로그인 전문 해석
인증 결과 전문 작성
WorkerThread.writeAsync()
현재 상태 = 요청 대기
요청 대기 :
요청 전문 해석
비즈니스 로직 수행
요청 수행 결과 전문 작성
WorkerThread.writeAsync()
현재 상태 = 요청 대기
20. New Non-blocking I/O – 장단점
• 장점
– 많은 수의 커넥션에서 고효율 고성능
– 많은 수의 커넥션에서 디버그 쉬움
• 단점
– 복잡한 스레드 모델
– 이해하기 어려운 다단계 State machine 기반
• Old I/O 에서 쉬웠던 것도 어렵게 구현
• SSL / TLS 암호화
• 전문 완전히 받을 때까지 기다리기
– 벤더별 SelectorProvider 구현 특성
22. The Netty Project
• 이벤트 기반 비동기 네트워크 어플리케이션 프레임워크
• Interceptor Chain 패턴
– 손쉽게 다단계 State machine 구현
– 암복호화 + 전문 해석 + 스레드 풀링 + 비즈니스 로직
– 조립 가능한 컴포넌트 다수 제공
• 과부하 및 DoS 방어 메커니즘
• Old · New I/O 모두 지원
• NIO 구현 · 벤더별 최적화
23. The Netty Project
• 주요 프로토콜 코덱 제공
– HTTP
– Google Protocol Buffers
• 제한된 환경 지원
– Android, Applet, WebStart
• 다양한 컨테이너 및 DI 프레임워크 지원
– JBoss Microcontainer, OSGi, Guice, Spring
24. Echo · Discard 예제 해부
부트스트랩
•
이벤트 핸들러
•
메모리 넘치지 않게 하기
•
핸들러 직접 구현해 보기
•
25. Telnet 예제 해부
• 구분자 기반
– 텍스트 (CR / LF) · 플래쉬 XML Socket (NUL) 등
– OneToOneEncoder
– DelimiterBasedFrameDecoder
26. Factorial 예제 해부
• 길이 필드 기반
– 일반적으로 바이너리
– 길이 필드를 포함한 헤더 + 바디
– OneToOneEncoder
– FrameDecoder
– ReplayDecoder
• 상태 관리
– 커넥션별 중간 계산값 저장
27. HTTP 서버 만들기
• HTTP 의 모든 면을 세세히 제어 가능
– 대용량 데이터 송수신 – Chunked Encoding
– Comet / AJAX
• 서버
– HttpRequestDecoder
– HttpResponseEncoder
• 클라이언트
– HttpRequestEncoder
– HttpResponseDecoder
28. Google Protocol Buffers
• 정의 파일에서 고성능 고효율 코드 생성
message Person {
message Person {
required string name = 1;
required string name = 1;
optional string email = 2;
optional string email = 2;
enum PhoneType {
enum PhoneType {
HOME = 0;
HOME = 0;
WORK = 1;
WORK = 1;
}
}
message PhoneNumber {
message PhoneNumber {
required string number = 1;
required string number = 1;
optional PhoneType type = 2 [default = HOME];
optional PhoneType type = 2 [default = HOME];
}
}
repeated PhoneNumber phone = 4;
repeated PhoneNumber phone = 4;
}
}
29. Netty + Google Protocol Buffers
• 고속 개발
– Encoder / Decoder 구현이 필요 없음
– 잘 작성된 정의 파일을 통해 하위 호환성 확보
• 상호 운용성 증대
– Java, C++, Python 등 대부분의 언어용 코드 자동 생성
• Netty 와 간단히 통합
– ProtobufEncoder
– LengthFieldPrepender
– ProtobufDecoder
– LengthFieldBasedFrameDecoder
30. 업무 적용 – 비즈니스 로직 수행
• 대부분의 비즈니스 로직은 외부 자원 접근
– Database CRUD
– 다른 서버로 릴레이 – Proxy
• NIO Worker 스레드에서 오래 걸리는 동작 수행 불가
– 다른 커넥션에 영향
• ChannelPipeline 에 ExecutionHandler 추가
– OrderedMemoryAwareThreadPoolExecutor
• 핸들러 내부에서 비동기 API 만 사용
– Asynchronous JDBC
– Netty in Netty
31. 업무 적용 – DoS 및 과부하 방어
• Message flooding
– (Ordered)MemoryAwareThreadPoolExecutor
– Write buffer high·low water mark
– Channel.isWritable() 존중
• 접속 후 요청 · 응답 없이 자원 소모하는 경우
– ReadTimeoutHandler
– WriteTimeoutHandler
– IdleStateHandler
32. 업무 적용 – DoS 및 과부하 방어
• 적극적 방어를 위해서는 비즈니스 로직에 맞게 최적화
• ' 의심스러운 ' 커넥션 제거
– Flooding 기준 정의
– 엄격한 전문 형식 · state machine 상태 유효성 검사
• 긴 전문은 Chunk 로 쪼개 처리