[e6]2012. netty internals

20
Netty Internals and Core Concepts 이희승 Twitter, Inc.

Upload: naver-d2

Post on 25-May-2015

8.718 views

Category:

Technology


2 download

TRANSCRIPT

Page 1: [E6]2012. netty internals

Netty Internals and Core Concepts이희승

Twitter, Inc.

Page 2: [E6]2012. netty internals

CONTENTS

● 소개

● 이벤트 모델

● 스레드 모델

● 테스팅

● 생각할 거리

Page 3: [E6]2012. netty internals

소개

● 네티란 ?

● 구성요소

– 이벤트 루프

– 파이프라인 (BiDiCoR)

Page 4: [E6]2012. netty internals

네티란 ?

● Java network application framework

– http://netty.io/

– @netty_project

● Asynchronous & event-driven

– High-throughput & highly concurrent connection

– .. with less resources – threads, memory & CPU cycles

● API as an I/O abstraction layer

– Works with NIO, OIO, AIO & more without many changes

● Well-defined event model & thread model

● Flexible event handling with bi-directional chain of responsibility pattern

● Promotes 'separation of concerns'

– I/O layer (Netty)

– Protocol codec (Netty or user)

– Business logic (user)

Page 5: [E6]2012. netty internals

구성요소

Buffers

I/O Abstraction – Channels, Event Loops, and Pipelines

In-VM

HTTP

TCP UDP

Custom Event Handlers & Codecs

Business Logic

Transports

User Code

Handlers

Core

Event Handlers

Codec Framework

Page 6: [E6]2012. netty internals

이벤트 루프

● Similar to..

– Windows event dispatcher

– Swing event loop

– Reactor

● 사용자의 I/O 요청을 처리

– 이벤트 루프 스레드 내에서 요청했을 경우 즉시

– 이벤트 루프 스레드 외에서 요청했을 경우 이벤트 루프의 작업 큐에 넣어 스케쥴

● 외부의 자극에 반응하고 파이프라인에 알림

– 데이터를 읽어들임

– 소켓 버퍼가 꽉 찼음

● 사용자가 원하는 임의 작업 실행

– One-time or periodic

Page 7: [E6]2012. netty internals

파이프라인

● BiDiCoR

– Bi-directional Chain of Responsibility pattern

– Similar to Servlet filters and decorator pattern

● Inbound event

– 이벤트 루프가 발생시킨 이벤트 ( 소켓 연결 , 데이터 수신 등 )

– 사용자가 작성한 inbound event handler 가 수신할 수 있도록 해 줌

● Outbound event

– 사용자가 요청한 동작 ( 쓰기 , 읽기 일시 중단 등 )

– 사용자가 작성한 outbound event handler 가 다른 핸들러에서 요청한 동작을 가로챌 수 있도록 해 줌

– 최종적으로 이벤트 루프에 전달되어 실제 I/O 가 수행되도록 함

● 예시

– [1:EvLoop] → [2:Protocol Decoder] → [3:Protocol Encoder] → [4:Business Logic]

– 수신 : 1 → 2 → 4

– 송신 : 4 → 3 → 1

Page 8: [E6]2012. netty internals

이벤트 모델

● Before, After & Considerations

Page 9: [E6]2012. netty internals

기존의 이벤트 모델

● 이벤트 = 자바 객체

● 예시

– ChannelOpen (instanceof ChannelStateEvent)

– ChannelBound (instanceof ChannelStateEvent)

– ChannelConnected (instanceof ChannelStateEvent)

– MessageEvent (inbound)

– MessageEvent (outbound)

– ChannelDisconnected (instanceof ChannelStateEvent)

– ChannelUnbound (instanceof ChannelStateEvent)

– ChannelClosed (instanceof ChannelStateEvent)

● Is GC cheap?

– No at extreme scale

● Can buffer pool beat JVM's memory allocator?

– Think memory bandwidth took by memset

– Modern concurrency constructs enable close-to-native efficiency in object pooling

● Too many state events!

– Open → bound → connected is an overkill in most TCP conns

– What's interesting to user is 'connected'.

● New buffer is created on every MessageEvent.

– GC pressure

– User has no control over the buffer

● Heap or direct

● Bounded or unbounded

● No buffered flush

– Every write is an immediate flush

– Sometimes not desired

Page 10: [E6]2012. netty internals

새 이벤트 모델

● 이벤트 = 메소드 호출

● 예시

– ChannelRegistered

– ChannelActive

– InboundBufferUpdated

– Flush

– ChannelInactive

– ChannelUnregistered

● 상태 전이 단순화

● 핸들러가 수신 및 송신 버퍼를 만들어 네티에게 제공하면 지속적으로 재사용

– 버퍼 해제 시점이 명확하므로 풀링 구현 단순화 가능

– 이벤트에 버퍼 정보가 없음

● Buffered flush

– 버퍼에 데이터를 채운 뒤 flush 이벤트를 발생시키는 것으로 MessageEvent 대체

– 여러 개의 메시지를 쓴 뒤 flush 하여 시스템 콜 절약

● 훨씬 적은 GC 빈도

– 이벤트 객체 생성 → 호출 스택

– 수신 및 송신 버퍼

● 단점

– 이벤트 유형별로 메소드를 전부 정의해야 함 ( 코드 중복 )

– 사용자 정의 이벤트 처리 어려움

● 별도로 UserEventTriggered 메소드 추가

Page 11: [E6]2012. netty internals

스레드 모델

● Why is well-defined thread model necessary?

Page 12: [E6]2012. netty internals

잘 정의된 스레드 모델의 필요성

● 프레임워크에서 사용자의 코드가 어느 스레드에서 언제 실행될 지 충분히 정확히 정의해야 함

● 프레임워크가 어느 정도의 thread safety 를 사용자 코드 (e.g. 이벤트 핸들러 ) 에게 제공할 것인가 ?

– 이벤트 간의 happens-before 관계

– 네티가 핸들러 메소드를 동시 실행하는 경우가 있는가

– 비동기 I/O 요청 이후에 완료 알림은 어느 스레드에서 실행되어야 하는가

– 사용자가 직접 동기화하도록 했을 때 dead lock 발생은 하지 않는가

● 정확한 스레드 모델이 제시되지 않으면 사용자 코드는 방어적으로 ( 또는 부정확하게 ) 작성됨

– 불필요한 동기화 및 그에 따른 dead lock ( 또는 부족한 동기화로 인한 race condition)

– 성능 저하 및 유지 보수 비용 증가

● 예 : 네티의 SSL 핸들러

– LoC: 1469 → 925 (3.5 vs 4.0)

Page 13: [E6]2012. netty internals

네티 4 스레드 모델

● 3.x 대비 이벤트 모델 개선과 함께 가장 중요하고 긍정적인 변화

● 네티는 핸들러가 @Sharable 어노테이션이 붙어 있는 경우가 아니면 절대 같은 핸들러 메소드를 동시에 호출하지 않는다 .

– 사용자는 자신이 작성한 핸들러 클래스의 메소드를 동기화할 필요가 없다 .

– 단 , 사용자는 같은 핸들러 인스턴스를 파이프라인에 여러 번 추가할 수 없다 .

● 네티가 핸들러 메소드를 호출할 때 각 호출 사이에는 happens-before 관계가 성립한다 .

– 사용자는 핸들러의 멤버 변수를 volatile 로 선언할 필요가 없다 .

● 이벤트루프는 항상 싱글 스레드로 실행된다 .

– 핸들러 메소드는 항상 같은 스레드로부터 호출된다 .

● 비동기 요청에 대한 결과 통보 (ChannelFuture) 는 이벤트 루프 스레드에서 항상 이루어진다 .

Page 14: [E6]2012. netty internals

테스팅

● 네티 유저의 테스트

● 네티 자체의 테스트

Page 15: [E6]2012. netty internals

네티 유저의 테스트

● 네티는 EmbeddedChannel 이라 불리는 Channel 구현을 제공

● 사용자는 자신이 작성한 핸들러를 EmbeddedChannel 의 파이프라인에 추가하고 이벤트를 임의로 발생시켜 테스트

@Test public void testLineProtocol() { EmbeddedByteChannel ch = new EmbeddedByteChannel(new LineDecoder());

// Ordinary input ch.writeInbound(Unpooled.wrappedBuffer(new byte[] { 'A' })); assertNull(ch.readInbound()); ch.writeInbound(Unpooled.wrappedBuffer(new byte[] { 'B' })); assertNull(ch.readInbound()); ch.writeInbound(Unpooled.wrappedBuffer(new byte[] { 'C' })); assertNull(ch.readInbound()); ch.writeInbound(Unpooled.wrappedBuffer(new byte[] { '\n' })); assertEquals(Unpooled.wrappedBuffer(new byte[] { 'A', 'B', 'C' }), ch.readInbound());

// Truncated input ch.writeInbound(Unpooled.wrappedBuffer(new byte[] { 'A' })); assertNull(ch.readInbound()); ch.close(); assertNull(ch.readInbound()); }

Page 16: [E6]2012. netty internals

네티 자체의 테스트

● 각 트랜스포트의 정확한 동작을 확인하기 위해 모든 트랜스포트 조합과 주요 프로토콜 조합에 대해 교차 테스트 수행

– TCP: NIO x AIO x OIO = 9 – 1 (OIO x OIO)

– UDP: NIO x OIO = 4

– 프로토콜 : Echo, SSL, SPDY = 3 * TCP (8) = 24

● 자체 제공 핸들러의 경우는 EmbeddedChannel 을 이용

● 기타

– Jenkins

– Animal Sniffer: Build fails on violation before packaging

– Checkstyle: Build fails on violation before compilation

Page 17: [E6]2012. netty internals

생각할 거리

● Dynamic event routing

● Statistical Distributed Performance Analysis on Mesos Cluster

● Management and Monitoring

● Native Transport

● Scalable Community

Page 18: [E6]2012. netty internals
Page 19: [E6]2012. netty internals
Page 20: [E6]2012. netty internals

유용할만한 곳

● 공식 자료

– 홈페이지 - http://netty.io/

– 4.0 변경 사항 모음 - http://goo.gl/E2BJ2

● 커뮤니티 자료

– 블로그 모음 - http://goo.gl/2iMKP

– 스택오버플로 - http://stackoverflow.com/questions/tagged/netty

● 네티 프로젝트 트위터 계정

– https://twitter.com/netty_project

● 네티 한국어 이용자 모임

– https://groups.google.com/forum/#!forum/netty-ko