- Leading Netty effort at Red Hat
- Vert.x / NIO / Performance
- Author of Netty in Action
- @normanmaurer
- github.com/normanmaurer
Netty is a NIO client server framework which enables quick and easy development of network applications …
Netty Website
Don’t call us, we’ll call you.
Hollywood principle
Usually a Thread takes memory from 256kb to 1mb for the stack space! Also a lot of wasted resources… |
http://www.flickr.com/photos/bibi/5204647994/
Once a `Channel was closed it can’t be reused. |
You can even deregister / re-register a Channel ! |
ByteBuf buf = ...;
buf.writeInt(1).writeBytes(data).writeBoolean(true)...
Pooling pays off for direct and heap buffers! |
https://blog.twitter.com/2013/netty-4-at-twitter-reduced-gc-overhead
ChannelInboundHandler
void channelRegistered(...) throws Exception;
void channelUnregistered(C...) throws Exception;
void channelActive(...) throws Exception;
void channelInactive(...) throws Exception;
void channelRead(...) throws Exception;
void channelReadComplete(...) throws Exception;
void userEventTriggered(...) throws Exception;
void channelWritabilityChanged(...) throws Exception;
void exceptionCaught(...) throws Exception;
These methods are called once there is something to handle by netty itself. |
ChannelOutboundHandler
void bind(..., ChannelPromise promise) throws Exception;
void connect(..., ChannelPromise promise) throws Exception;
void disconnect(..., ChannelPromise promise) throws Exception;
void close(..., ChannelPromise promise) throws Exception;
void deregister(..., ChannelPromise promise) throws Exception;
void read(...) throws Exception;
void write(..., ChannelPromise promise) throws Exception;
void flush(...) throws Exception;
These methods are called once a User requests some action via for example Channel.close(...) . |
Helps against GC pressure… |
http://25.media.tumblr.com/tumblr_me2eq0PnBx1rtu0cpo1_1280.jpg
@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();
}
}
1 | Intercept received message and write it back to the remote peer |
2 | React on Throwable and close the connection |
ByteToMessageDecoder |
Bytes → Pojo with handling of buffering
public class ByteToMessageDecoderImpl extends ByteToMessageDecoder {
@Override
public void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) { }
}
MessageToMessageDecoder |
Pojo → Pojo
public class MessageToMessageDecoderImpl extends ByteToMessageDecoder<Pojo> {
@Override
public void decode(ChannelHandlerContext ctx, Pojo in, List<Object> out) { }
}
MessageToByteEncoder |
Pojo → Bytes
public class MessageToByteEncoderImpl extends MessageToByteEncoder<Pojo> {
@Override
public void encode(ChannelHandlerContext ctx, Pojo in, ByteBuf out) { }
}
MessageToMessageEncoder |
Pojo → Pojo
public class MessageToMessageEncoderImpl extends MessageToMessageEncoder<Pojo> {
@Override
public void encode(ChannelHandlerContext ctx, Pojo in, List<Object> out) { }
}
ChannelHandlers
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! |
Events move through the ChannelPipeline
Channel ch = ...;
ChannelPipeline p = ch.pipeline();
EventExecutor e1 = new DefaultEventExecutor(16);
EventExecutor e2 = new DefaultEventExecutor(8);
p.addLast(new MyProtocolCodec()); (1)
p.addLast(e1, new MyDatabaseAccessingHandler()); (2)
p.addLast(e2, new MyHardDiskAccessingHandler()); (3)
1 | Executed in EventLoop (and so the Thread bound to it) |
2 | Executed in one of the EventExecutors of e1 |
3 | Executed in one of the EventExecutors of e2 |
http://www.flickr.com/photos/stavos52093/9645884201/
Channels
No need to worry about synchronization |
http://www.flickr.com/photos/za3tooor/65911648/
Multiple Channels are assigned to one EventLoop
ScheduleExecutorService
goodies for free!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)
}
}
}
1 | Schedule task for in 30 seconds |
ServerBootstrap b = new ServerBootstrap();
EventLoopGroup group = new NioEventLoopGroup(numThreads);
try {
b.group(group, group)
.channel(NioServerSocketChannel.class)
.localAddress(new InetSocketAddress(25))
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) {
ch.pipeline().addLast(new YourChannelHandler());
}
});
ChannelFuture f = b.bind().sync();
f.channel().closeFuture().sync();
} finally {
group.shutdownGracefully();
}
Bootstrap b = new Bootstrap();
EventLoopGroup group = new NioEventLoopGroup(numThreads);
try {
b.group(group)
.channel(NioSocketChannel.class)
.remoteAddress(new InetSocketAddress("10.0.0.1", 25))
.handler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) {
ch.pipeline().addLast(new YourChannelHandler());
}
});
ChannelFuture f = b.connect().sync();
f.channel().closeFuture().sync();
} finally {
group.shutdownGracefully();
}
Can be used for maximal performance on Linux |
Channel
re-registerForkJoinPool
based EventLoop
SSLEngine
Check issue tracker to stay up-to-date. |
https://github.com/netty/netty/issues
… and many more … |
… and many more … |
http://www.flickr.com/photos/legofenris/4499417549/
Mailinglist - https://groups.google.com/forum/#!forum/netty |
IRC - #netty irc.freenode.org |
Website - http://netty.io |
Source / issue tracker - https://github.com/netty/netty/ |
Buy my book Netty in Action and make me RICH. |
http://www.manning.com/maurer
$ KA-CHING $
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 orCreative Commons Attribution-Share Alike |