reactive server with netty
TRANSCRIPT
![Page 1: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/1.jpg)
Highload reactive server with Netty
![Page 2: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/2.jpg)
Dmitriy DumanskiyBlynk, CTO
Java blog : https://habrahabr.ru/users/doom369/topicsDOU : https://dou.ua/users/DOOM/articles/
![Page 3: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/3.jpg)
Makers problem
+ = ?
![Page 4: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/4.jpg)
Makers problem
● Http/s● Mqtt● WebSockets● Own binary protocol
![Page 5: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/5.jpg)
Blynk
10000 req/sec3 VM * 2 cores, 60$
25% load10k of local installations
![Page 6: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/6.jpg)
Why netty?
CassandraApache Spark
Elasticsearch
Graylog
Neo4j
Vert.x
HornetQInfinispan
Finagle
Async-http-clientFirebase
Akka
CouchbasePlay frameworkRedisson
![Page 7: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/7.jpg)
Why netty?
~700k servers
![Page 8: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/8.jpg)
Why netty?● Less GC
![Page 9: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/9.jpg)
Why netty?● Less GC● Optimized for Linux based OS
![Page 10: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/10.jpg)
Why netty?● Less GC● Optimized for Linux based OS● High performance buffers
![Page 11: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/11.jpg)
Why netty?● Less GC● Optimized for Linux based OS● High performance buffers● Well defined threading model
![Page 12: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/12.jpg)
Why netty?● Less GC● Optimized for Linux based OS● High performance buffers● Well defined threading model● HTTP, HTTP/2, SPDY, SCTP, TCP,
UDP, UDT, MQTT, etc
![Page 13: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/13.jpg)
When to use?● Performance is critical
![Page 14: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/14.jpg)
When to use?● Performance is critical● Own protocol
![Page 15: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/15.jpg)
When to use?● Performance is critical● Own protocol● Full control over network
(so_reuseport, tcp_cork, tcp_fastopen, tcp_nodelay, etc)
![Page 16: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/16.jpg)
When to use?● Performance is critical● Own protocol● Full control over network● Game engines (agario, slither,
minecraft)
![Page 17: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/17.jpg)
When to use?● Performance is critical● Own protocol● Full control over network● Game engines● <3 reactive
![Page 18: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/18.jpg)
Non-Blocking
● Few threads● No context switching● No memory consumption
![Page 19: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/19.jpg)
Non-Blockingnew Channel
read / write
Selector
Thread
new Channel
read / write
new Channel
read / write
![Page 20: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/20.jpg)
java.nio.channels.SelectorSelector selector = Selector.open();channel.configureBlocking(false);SelectionKey key = channel.register(selector, SelectionKey.OP_READ);while(true) { selector.select(); Set<SelectionKey> selectedKeys = selector.selectedKeys(); Iterator<SelectionKey> keyIterator = selectedKeys.iterator(); while(keyIterator.hasNext()) { key = keyIterator.next(); if (key.isReadable()) { ... } }}
![Page 21: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/21.jpg)
Selector selector = Selector.open(); // creating selectorchannel.configureBlocking(false);SelectionKey key = channel.register(selector, SelectionKey.OP_READ);while(true) { selector.select(); Set<SelectionKey> selectedKeys = selector.selectedKeys(); Iterator<SelectionKey> keyIterator = selectedKeys.iterator(); while(keyIterator.hasNext()) { key = keyIterator.next(); if (key.isReadable()) { ... } }}
![Page 22: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/22.jpg)
Selector selector = Selector.open(); channel.configureBlocking(false);//registering channel with selector, listening for READ events onlySelectionKey key = channel.register(selector, SelectionKey.OP_READ);while(true) { selector.select(); Set<SelectionKey> selectedKeys = selector.selectedKeys(); Iterator<SelectionKey> keyIterator = selectedKeys.iterator(); while(keyIterator.hasNext()) { key = keyIterator.next(); if (key.isReadable()) { ... } }}
![Page 23: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/23.jpg)
Selector selector = Selector.open();channel.configureBlocking(false);SelectionKey key = channel.register(selector, SelectionKey.OP_READ);while(true) { selector.select(); //blocking until we get some READ events Set<SelectionKey> selectedKeys = selector.selectedKeys(); Iterator<SelectionKey> keyIterator = selectedKeys.iterator(); while(keyIterator.hasNext()) { key = keyIterator.next(); if (key.isReadable()) { ... } }}
![Page 24: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/24.jpg)
Selector selector = Selector.open();channel.configureBlocking(false);SelectionKey key = channel.register(selector, SelectionKey.OP_READ);while(true) { selector.select(); //now we have channels with some data Set<SelectionKey> selectedKeys = selector.selectedKeys(); Iterator<SelectionKey> keyIterator = selectedKeys.iterator(); while(keyIterator.hasNext()) { key = keyIterator.next(); if (key.isReadable()) { ... } }}
![Page 25: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/25.jpg)
Selector selector = Selector.open();channel.configureBlocking(false);SelectionKey key = channel.register(selector, SelectionKey.OP_READ);while(true) { selector.select(); Set<SelectionKey> selectedKeys = selector.selectedKeys(); Iterator<SelectionKey> keyIterator = selectedKeys.iterator(); while(keyIterator.hasNext()) { key = keyIterator.next(); //do something with data if (key.isReadable()) { key.channel() } }}
![Page 26: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/26.jpg)
FlowSelector
SelectionKey
Channel
ChannelPipeline
![Page 27: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/27.jpg)
FlowChannelPipeline
fireEvent()
invokeChannelRead() executor.execute()
invokeChannelRead()
![Page 28: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/28.jpg)
Minimal setupServerBootstrap b = new ServerBootstrap();b.group( new NioEventLoopGroup(1), new NioEventLoopGroup()) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer() {...});
ChannelFuture f = b.bind(8080).sync();f.channel().closeFuture().sync();
![Page 29: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/29.jpg)
Minimal setupServerBootstrap b = new ServerBootstrap();b.group( new NioEventLoopGroup(1), //IO thread new NioEventLoopGroup()) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer() {...});
ChannelFuture f = b.bind(8080).sync();f.channel().closeFuture().sync();
![Page 30: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/30.jpg)
Minimal setupServerBootstrap b = new ServerBootstrap();b.group( new NioEventLoopGroup(1), new NioEventLoopGroup() //worker threads) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer() {...});
ChannelFuture f = b.bind(8080).sync();f.channel().closeFuture().sync();
![Page 31: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/31.jpg)
Minimal setupServerBootstrap b = new ServerBootstrap();b.group( new NioEventLoopGroup(1), new NioEventLoopGroup() //worker threads) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer() {...}); //pipeline init
ChannelFuture f = b.bind(8080).sync();f.channel().closeFuture().sync();
![Page 32: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/32.jpg)
Minimal setup
new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) { final ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new MyLogicHere()); }};
![Page 33: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/33.jpg)
ChannelPipeline
![Page 34: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/34.jpg)
ChannelPipeline
● Inbound event -> ChannelInboundHandler (CIHA)
● Outbound event -> ChannelOutboundHandler (COHA)
![Page 35: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/35.jpg)
ChannelInboundHandlerpublic interface ChannelInboundHandler extends ChannelHandler { ... void channelRegistered(ChannelHandlerContext ctx); void channelActive(ChannelHandlerContext ctx); void channelRead(ChannelHandlerContext ctx, Object msg); void userEventTriggered(ChannelHandlerContext ctx, Object evt); void channelWritabilityChanged(ChannelHandlerContext ctx); ...}
![Page 36: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/36.jpg)
void initChannel(SocketChannel ch) { ch.pipeline() .addLast(new MyProtocolDecoder()) .addLast(new MyProtocolEncoder()) .addLast(new MyLogicHandler());}
Own tcp/ip server
![Page 37: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/37.jpg)
Channel
MyProtocolDecoder
MyLogicHandler
Own tcp/ip server
Channel
MyProtocolEncoder
MyLogicHandler
![Page 38: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/38.jpg)
HandlersHttpServerCodec
ChannelTrafficShapingHandler
IdleStateHandler
ReadTimeoutHandler
ChunkedWriteHandler
SslHandler
LoggingHandler
RuleBasedIpFilter
StringDecoderJsonObjectDecoder
Base64DecoderJZlibDecoder
JZlibDecoder
Lz4FrameDecoder
ProtobufDecoderObjectDecoder
XmlFrameDecoder
![Page 39: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/39.jpg)
void initChannel(SocketChannel ch) { ch.pipeline() .addLast(new HttpRequestDecoder()) .addLast(new HttpResponseEncoder()) .addLast(new MyHttpHandler());}
Http Server
![Page 40: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/40.jpg)
void initChannel(SocketChannel ch) { ch.pipeline() .addLast(new HttpServerCodec()) .addLast(new MyHttpHandler());}
OR
![Page 41: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/41.jpg)
void initChannel(SocketChannel ch) { ch.pipeline() .addLast(sslCtx.newHandler(ch.alloc())) .addLast(new HttpServerCodec()) .addLast(new MyHttpHandler());}
Https Server
![Page 42: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/42.jpg)
void initChannel(SocketChannel ch) { ch.pipeline() .addLast(sslCtx.newHandler(ch.alloc())) .addLast(new HttpServerCodec()) .addLast(new HttpContentCompressor()) .addLast(new MyHttpHandler());}
Https Server + content gzip
![Page 43: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/43.jpg)
@Overridepublic void channelRead(Context ctx, Object msg) { //pass flow processing to next handler super.channelRead(ctx, msg);}
Pipeline flow
![Page 44: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/44.jpg)
@Override public void channelRead(Context ctx, Object msg) { //stop request processing return;}
Pipeline flow
![Page 45: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/45.jpg)
public void channelRead(Context ctx, Object msg) { If (msg instanceOf LoginMessage) { LoginMessage login = (LoginMessage) msg; if (isSuperAdmin(login)) { ctx.pipeline().remove(this); ctx.pipeline().addLast(new SuperAdminHandler()); } }}
Pipeline flow on the fly
![Page 46: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/46.jpg)
public void channelRead(Context ctx, Object msg) { ChannelFuture cf = ctx.writeAndFlush(response); cf.addListener(new ChannelFutureListener() { @Override public void complete(ChannelFuture future) { future.channel().close(); } });}
Pipeline futures
![Page 47: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/47.jpg)
@Overridepublic void channelRead(Context ctx, Object msg) { ChannelFuture cf = ctx.writeAndFlush(response); //close connection after message was delivered cf.addListener(ChannelFutureListener.CLOSE);}
Pipeline futures
![Page 48: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/48.jpg)
@Overridepublic void channelRead(Context ctx, Object msg) { ... ChannelFuture cf = ctx.writeAndFlush(response); cf.addListener(future -> { ... });}
Pipeline futures
![Page 49: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/49.jpg)
public void channelRead(Context ctx, Object msg) { ChannelFuture cf = session.sendMsgToFriend(msg); cf.addListener(new ChannelFutureListener() { @Override public void complete(ChannelFuture future) { future.channel().writeAndFlush(“Delivered!”); } });}
Pipeline futures
![Page 50: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/50.jpg)
Pipeline blocking IONon blocking pools Blocking pools
IO Event LoopsDB
Worker Event Loops
Mailing
File system
![Page 51: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/51.jpg)
public void channelRead(Context ctx, Object msg) { if (msg instanceof HttpRequest) { HttpRequest req = (HttpRequest) msg; if (req.method() == GET && req.uri().eq(“/users”)) { Users users = dbManager.userDao.getAllUsers(); ctx.writeAndFlush(new Response(users)); } }}
Pipeline blocking IO
![Page 52: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/52.jpg)
public void channelRead(Context ctx, Object msg) { if (msg instanceof HttpRequest) { HttpRequest req = (HttpRequest) msg; if (req.method() == POST && req.uri().eq(“/email”)) { mailManager.sendEmail(); } }
Pipeline blocking IO
![Page 53: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/53.jpg)
public void channelRead(Context ctx, Object msg) { if (msg instanceof HttpRequest) { HttpRequest req = (HttpRequest) msg; if (req.method() == GET && req.uri().eq(“/property”)) { String property = fileManager.readProperty(); ctx.writeAndFlush(new Response(property)); } }}
Pipeline blocking IO
![Page 54: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/54.jpg)
public void channelRead(Context ctx, Object msg) { ...
blockingThreadPool.execute(() -> {Users users = dbManager.userDao.getAllUsers();ctx.writeAndFlush(new Response(users));
});}
Pipeline blocking IO
![Page 55: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/55.jpg)
Pipeline blocking IO
● Thread.sleep()
![Page 56: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/56.jpg)
Pipeline blocking IO
● Thread.sleep()● java.util.concurrent.*
![Page 57: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/57.jpg)
Pipeline blocking IO
● Thread.sleep()● java.util.concurrent.*● Intensive operations
![Page 58: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/58.jpg)
Pipeline blocking IO
● Thread.sleep()● java.util.concurrent.*● Intensive operations● Any blocking IO (files, db, smtp, etc)
![Page 59: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/59.jpg)
Pipeline blocking IO
● Thread.sleep()● java.util.concurrent.*● Intensive operations● Any blocking IO (files, db, smtp, etc)
![Page 60: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/60.jpg)
@Overridepublic void channelInactive(Context ctx) { HardwareState state = getState(ctx.channel()); if (state != null) { ctx.executor().schedule( new DelayedPush(state), state.period, SECONDS ); }}
EventLoop is Executor!
![Page 61: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/61.jpg)
public void channelRead(Context ctx, Object msg) { if (msg instanceof FullHttpRequest) { FullHttpRequest request = (FullHttpRequest) msg; User user = sessionDao.checkCookie(request); ... } super.channelRead(ctx, msg); }
Request state
![Page 62: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/62.jpg)
private static AttributeKey<User> USER_KEY = AttributeKey.valueOf("user");
ctx.channel().attr(USER_KEY).set(user);
Request state
![Page 63: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/63.jpg)
public void channelRead(Context ctx, Object msg) { if (msg instanceof FullHttpRequest) { FullHttpRequest request = (FullHttpRequest) msg; User user = sessionDao.checkCookie(request); ctx.channel().attr(USER_KEY).set(user); } super.channelRead(ctx, msg); }
Request state
![Page 64: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/64.jpg)
if (isSsl(in)) { enableSsl(ctx);} else { if (isGzip()) { enableGzip(ctx); } else if (isHttp(in)) { switchToHttp(ctx); }}
Port unification
![Page 65: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/65.jpg)
![Page 66: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/66.jpg)
Back pressure
if (channel.isWritable()) { channel.writeAndFlush(msg);}
![Page 67: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/67.jpg)
Back pressure
BackPressureHandler
coming soon...
![Page 68: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/68.jpg)
Performance
![Page 69: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/69.jpg)
Performance
https://www.techempower.com/benchmarks/#section=data-r13&hw=ph&test=plaintext
![Page 70: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/70.jpg)
<dependency> <groupId>io.netty</groupId> <artifactId>netty-transport-native-epoll</artifactId> <version>${netty.version}</version> <classifier>${os}</classifier></dependency>
Native transport
![Page 71: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/71.jpg)
Bootstrap b = new Bootstrap();b.group(new EpollEventLoopGroup());b.channel(EpollSocketChannel.class);
Native transport
![Page 72: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/72.jpg)
SslContextBuilder.forServer().sslProvider(SslProvider.OpenSsl);
JNI OpenSslEngine
![Page 73: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/73.jpg)
<dependency> <groupId>io.netty</groupId> <artifactId>netty-tcnative-boringssl-static</artifactId> <version>${netty.boring.ssl.version}</version> <classifier>${os}</classifier></dependency>
JNI OpenSslEngine
![Page 74: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/74.jpg)
● Netty-tcnative● netty-tcnative-libressl● netty-tcnative-boringssl-static
JNI OpenSslEngine
![Page 75: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/75.jpg)
Own ByteBuf
![Page 76: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/76.jpg)
Own ByteBuf● Reference counted● Pooling by default● Direct memory by default● LeakDetector by default● Reduced branches, range-checks
![Page 77: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/77.jpg)
Own ByteBuf
● ByteBufAllocator.buffer(size);● ctx.alloc().buffer(size);● channel.alloc().buffer(size);
![Page 78: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/78.jpg)
Less system calls
for (Message msg : messages) { ctx.writeAndFlush(msg);}
![Page 79: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/79.jpg)
Less system calls
for (Message msg : messages) { ctx.write(msg);}ctx.flush();
![Page 80: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/80.jpg)
Thread Model
ChannelFuture inCf = ctx.deregister();
inCf.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture cf) {
targetLoop.register(cf.channel())
.addListener(completeHandler);
}
});
![Page 81: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/81.jpg)
Reusing Event Loop
new ServerBootstrap().group(new EpollEventLoopGroup(1), new EpollEventLoopGroup()
).bind(80);
![Page 82: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/82.jpg)
Reusing Event LoopEventLoopGroup boss = new EpollEventLoopGroup(1);
EventLoopGroup workers = new EpollEventLoopGroup();
new ServerBootstrap().group(
boss,
workers
).bind(80);
new ServerBootstrap().group(
boss,
workers
).bind(443);
![Page 83: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/83.jpg)
Use direct buffers
ctx.writeAndFlush(
new ResponseMessage(messageId, OK)
);
![Page 84: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/84.jpg)
Use direct buffers
ByteBuf buf = ctx.alloc().buffer(3);//pool
buf.writeByte(messageId);
buf.writeShort(OK);
ctx.writeAndFlush(buf);
![Page 85: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/85.jpg)
Less allocations
ByteBuf msg = makeResponse(...);msg.retain(targets.size() - 1);
for (Channel ch : targets) { ch.writeAndFlush(msg);}
![Page 86: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/86.jpg)
Void promise
ctx.writeAndFlush(
response
);
![Page 87: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/87.jpg)
Void promise
ctx.writeAndFlush(
response, ctx.voidPromise()
);
![Page 88: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/88.jpg)
Reuse handlers
@Sharable
public class StringDecoder extends MessageToMessageDecoder<ByteBuf> {
...
}
![Page 89: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/89.jpg)
Prefer context
ctx.channel().writeAndFlush();
![Page 90: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/90.jpg)
Prefer context
ctx.channel().writeAndFlush();
ctx.writeAndFlush();
![Page 91: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/91.jpg)
Simpler - faster
ChannelInboundHandlerAdapter
does nothing, but fast
![Page 92: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/92.jpg)
Simpler - faster
ByteToMessageDecoder
does some work, but slower
![Page 93: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/93.jpg)
Simpler - faster
ReplayingDecoder
does job for you, but slowest
![Page 94: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/94.jpg)
Turn off leak detection
ResourceLeakDetector.setLevel(
ResourceLeakDetector.Level.DISABLED);
![Page 95: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/95.jpg)
What else?
● ASCIIString● FastThreadLocal● Unsafe● Optimized Encoders
![Page 96: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/96.jpg)
● Really fast● Low GC load● Flexible● Rapidly evolve● Cool support
Summary
![Page 97: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/97.jpg)
● Hard● Memory leaks● Still have issues
Summary
![Page 98: Reactive server with netty](https://reader033.vdocuments.site/reader033/viewer/2022050800/5aaba8067f8b9ac7658b4677/html5/thumbnails/98.jpg)
https://github.com/blynkkk/blynk-server