Netty 4 - A look behind the scenes

Norman Maurer, Principal Software Engineer @ Red Hat Inc

  • Netty / Vert.x / All things NIO
  • Author of Netty in Action
  • @normanmaurer
  • github.com/normanmaurer

Agenda

  • Introducing Netty
  • Vert.x case-study

What is Netty?

Netty is a NIO client server framework which enable quick and easy development of network applications such as protocol servers and clients…


Netty Website

Features Netty comes with…

components

Asynchronous and non blocking by nature

  • I/O Operations don’t block at all!
  • Notified later
  • Share one Thread

Don’t call us, we’ll call you.


Hollywood principle

But why non-blocking at all ?

Usually a Thread takes memory from 256kb to 1mb for the stack space! Also a lot of wasted resources…
ouch
hhttp://www.flickr.com/photos/bibi/5204647994/

Asynchronous in Action

Channel channel = ...
ChannelFuture cf = channel.writeAndFlush(data); (1)
cf.addListener(new ChannelFutureListener() {    (2)
  @Override
  public void operationComplete(ChannelFuture future) {
    if(!future.isSuccess() {
        future.cause().printStacktrace();
    } else { ... }
  }
});
1Write to the Channel and flush
2Add ChannelFutureListener to be notified once operations completes

ByteBuf - ByteBuffer on steroids!

  • Separate index for reader/writer
  • Direct, Heap and Composite
  • Resizable with max capacity
  • Reference counting
ByteBuf buf = ...;
buf.writeInt(1).writeBytes(data).writeBoolean(true)...

ByteBuf pooling to reduce allocation / deallocation time!

Pooling pays off for direct and heap buffers!
pooled buffers
https://blog.twitter.com/2013/netty-4-at-twitter-reduced-gc-overhead

ChannelHandlers - Where your handling logic lifes

  • Inbound and Outbound
  • Called by the EventExecutor
channel handlers

ChannelHandler in Action

@Sharable
public class EchoHandler extends ChannelInboundHandlerAdapter {
  @Override
  public void channelRead(ChannelHandlerContext ctx, Object msg) { (1)
    ctx.writeAndFlush(msg);
  }

  @Override
  public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { (2)
    cause.printStacktrace();
    ctx.close();
  }
}
1Intercept received message and write it back to the remote peer
2React on Throwable and close the connection

ChannelPipeline - Chain ChannelHandlers

  • Holds ChannelHandlers
  • Per Channel
  • Events pass through
Kind of a unix-pipe-like thing…
$ echo "Netty is shit...." | sed -e 's/is /is the /'
                    Netty is the shit....
You see, everything is adjustable!

EventLoop - Someone needs to do the heavy work

No need to worry about synchronization
thumb up 2
http://www.flickr.com/photos/za3tooor/65911648/

EventLoop - All the ScheduleExecutorService goodies for free!

eventexecutor
public class WriteTimeOutHandler extends ChannelOutboundHandlerAdapter {
  @Override
  public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
    ctx.write(msg, promise);

    if (!promise.isDone() {
      ctx.executor().schedule(new WriteTimeoutTask(promise), 30, TimeUnit.SECONDS); (1)
    }
  }
}
1Schedule task for in 30 seconds

Using Netty in your next application / framework!

vertx
A case study for using Netty based on Vert.x!

Often you need to expose callbacks to your users, but these not always match.

Used in Vert.x as callback for outbound operations
public interface Handler<E> {
  void handle(E event);
}
Used in Netty as callback for outbound operations.
public interface ChannelFutureListener {
  void operationComplete(ChannelFuture future) throws Exception;
}

public interface ChannelOutboundHandler extends ChannelHandler {
  void write(ChannelHandlerContext ctx, Object msg,
      ChannelPromise promise) throws Exception;
  ...
}

Create adapter classes for Outbound operations.

public class HandlerAdapter<AsyncResult<T>> implements ChannelFutureListener {
  public HandlerAdapter(Handler<AsyncResult<T>> handler, T okResult) { ... }
  @Override
  public void operationComplete(ChannelFuture future) {
    if (future.isSuccess()) {
      handler.handle(new DefaultFutureResult<T>(okResult));
    } else {
      handler.handle(new DefaultFutureResult<T>(future.cause()));
    }
  }
}
public DefaultNetSocket implements NetSocket {
  @Override
  public void sendFile(String name, Handler<AsyncResult<NetSocket> callback) {
    channel.writeAndFlush(createFileRegion(name)).addListener(
        new HandlerAdapter(callback, this));
  }
}

Notifications

Used in Vert.x as callback for inbound events
public interface Handler<E> {
  void handle(E event);
}
Used in Netty as callback for inbound events.
public interface ChannelInboundHandler extends ChannelHandler {
  void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception;

  void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception;
  ...

Create adapter classes for inbound events.

public class InboundHandlerAdapter<T> extends ChannelInboundHandlerAdapter {
  public InboundHandlerAdapter(Handler<T> dataHandler,
      Handler<Throwable> exceptionHandler) { ... }

  @Override
  public void channelRead(ChannelHandlerContext ctx, Object msg) {
    handler.handle((T) msg);
  }

  @Override
  public void exceptionCaught(ChannelHandlerCtx ctx, Throwable cause) {
    exceptionHandler.handle(cause);
  }
}

Companies using Netty!

companies
… and many more …

We love Contributions!

empire wants you 2
http://www.flickr.com/photos/legofenris/4499417549/

Want to know more?

Buy my book Netty in Action and make me RICH.
maurer cover150
http://www.manning.com/maurer

$ KA-CHING $

References

Netty - http://netty.io
Slides generated with Asciidoctor and DZSlides backend
Original slide template - Dan Allen & Sarah White
All pictures licensed with Creative Commons Attribution or
Creative Commons Attribution-Share Alike

Norman Maurer