netty indroduction

26
Netty5.0 Overview LAURENCE HO, JAN 2016 6/28/22 1

Upload: laurence-ho

Post on 25-Jan-2017

555 views

Category:

Engineering


0 download

TRANSCRIPT

Page 1: Netty indroduction

May 1, 2023 1

Netty5.0 OverviewLAURENCE HO, JAN 2016

Page 2: Netty indroduction

May 1, 2023 2

AgendaWhat is Netty?

Blocking and Non-Blocking

Asynchronous

Main Components

IP Address Filter

Security Issues

Serialization via Protocol Buffers

Page 3: Netty indroduction

May 1, 2023 3

What is Netty?1. non-blocking I/O (NIO) client-server framework

2. asynchronous event-driven network application framework

3. multi-protocol supporting

Page 4: Netty indroduction

May 1, 2023 4

Benefits of NettyUnified API for various transport types - blocking and non-blocking socket

Highly customizable thread model - single thread, one or more thread pools such as SEDA

No additional dependencies, JDK 5 (Netty 3.x) or 6 (Netty 4.x) is enough

Better throughput, lower latency

Less resource consumption

Complete SSL/TLS and StartTLS support

Page 5: Netty indroduction

May 1, 2023 5

Blocking and Non-Blocking Blocking I/O (OIO):

Socket

Read/Write

Thread

Socket

Read/Write

Thread

Socket

Read/Write

Thread

Socket

Read/Write

Thread

Page 6: Netty indroduction

May 1, 2023 6

Blocking and Non-Blocking Non-blocking I/O (NIO):

Socket

Read/Write

Selector

Thread

Socket

Read/Write

Socket

Read/Write

Socket

Read/Write

Page 7: Netty indroduction

May 1, 2023 7

Blocking and Non-Blocking OIO:

NIO:

BufferedReader in = new BufferedReader( InputStreamReader(clientSocket.getInputStream())); PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true); String request, response; while ((request = in.readLine()) != null) {

if ("Done".equals(request)) { break;

} } response = processRequest(request);out.println(response);

While(true){selector.select(); //request events from multiple channelsIterator it = selector.selectedKeys().iterator();while(it.hasNext()){

SelectorKey key = (SelectionKey) it.next();handleKey(key);it.remove();

}}

Page 8: Netty indroduction

May 1, 2023 8

AsynchronousAll I/O operations do not block

Get notification when the operation completed

Be able to share threads across many connections

In os: o select()/poll(): traditional POSIX pollingo epoll(): event-based polling, on Linux 2.5.44+o kqueue: on FreeBSD, Mac OS X

Java example:Channel channel = ...;ChannelFuture future = channel.connect( new InetSocketAddress("192.168.0.1", 25));

Page 9: Netty indroduction

May 1, 2023 9

Echo client & server

Client1

Client2

Client3

Hello

Hello

Hello

World

World

World

ServerConnection1

Connection2Connection3

Page 10: Netty indroduction

May 1, 2023 10

Main ComponentsBootstrap and ServerBootstrap

EventLoop

Channel

ChannelFuture

ChannelPipeline

ChannelHandlers

ChannelHandlerContext

Page 11: Netty indroduction

May 1, 2023 11

Bootstrapping a server

ServerBootstrap bind() ServerChannel

Channel1 Channel1 Channel1

A ServerChannel is created when bind() is called.

A new Channel is created by the ServerChannel when a connection is accepted.

Page 12: Netty indroduction

May 1, 2023 12

Bootstrapping a client

Bootstrapbind()

connect()

Channel1

Channel1

Bootstrap will create a new Channel after bind() has been called, after which

connect() is called to establish the connection.

Bootstrap will create a new channel when connect() is called.

Page 13: Netty indroduction

May 1, 2023 13

Bootstrapping clients from a Channel

ServerBootstrap bind() ServerChannel

Channel Bootstrap connect() Channel

EventLoop

ServerBootstrap creates a new ServerChannel when bind() is called.

ServerChannel accepts new connections and creates child channels to serve them.

Channel created for an accepted connection.

Bootstrap created by the Channel will create a new Channel when connect() is called.

Page 14: Netty indroduction

May 1, 2023 14

Bootstrap, EventLoop and Channel

A Bootstrap that makes it easy to bootstrap a Channel to use for clients.

An EventLoopGroup contains one or more EventLoops.

EventLoop handles all the I/O operations for a Channel once registered.

All I/O events processed by an EventLoop are handled on its dedicated Thread.

A Channel is registered for its lifetime with a single EventLoop.

EventLoopGroup workerGroup = new NioEventLoopGroup();try { ServerBootstrap b = new ServerBootstrap(); b.group(workerGroup).channel(NioSocketChannel.class)

.handler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new SimpleServerHandler()); } }).option(ChannelOption.SO_KEEPALIVE, true);

// Bind and start to accept incoming connections. ChannelFuture f = b.bind(port).sync();

// Wait until the server socket is closed. f.channel().closeFuture().sync();} finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully();}

Page 15: Netty indroduction

May 1, 2023 15

Bootstrap, EventLoop and Channel

EventLoopGroup With 3

EventLoopsEventLoop

Create Channel1 Register EventLoop with Channel

Process I/O with EventLoop during entire lifetime

Channel1

EventLoopEventLoop

EventLoop

Channel1

EventLoop

Channel1

Page 16: Netty indroduction

May 1, 2023 16

The Channel LifecycleState Description

ChannelUnregistered The Channel was created, but isn’t registered to an EventLoop.

ChannelRegistered The Channel is registered to an EventLoop.

ChannelActive The Channel is active (connected to its remote peer). It’s now possible to receive and send data.

ChannelInactive The Channel isn’t connected to the remote peer.

ChannelRegistered ChannelActive

ChannelInactive ChannelUnregistered

Page 17: Netty indroduction

May 1, 2023 17

ChannelFutureDo asynchronous

Its addListener() method registers a ChannelFutureListener to be notified when an operation has completed (whether or not successfully).

Example: ChannelFuture f = ctx.writeAndFlush(time);f.addListener(new ChannelFutureListener() { public void operationComplete(ChannelFuture future) { assert f == future; ctx.close(); }});

Page 18: Netty indroduction

May 1, 2023 18

ChannelPipelineEvery connection(channel) is attached to a ChannelPipeline

One ChannelPipeline one connection(channel)

All events get passed through it

It contains a stack of ChannelHandlers:o Protocol: encoders & decoderso Security layers: SSL/TLS, authenticationo A custom handlero Others...

Example: ChannelPipeline pipeline = ch.pipeline();pipeline.addLast(sslCtx.newHandler(ch.alloc()));pipeline.addLast(new StringDecoder());pipeline.addLast(new StringEncoder());pipeline.addLast(new SimpleServerHandler()); // A custom handler

Page 19: Netty indroduction

May 1, 2023 19

ChannelHandlersEverything is an event

Process message(event): reading and writing

Inbound message or outbound message

Check status or do operations

Connection established or shout down

Byte or message based

Example: public class SimpleServerHandler extends ChannelHandlerAdapter {@Override public void channelRead(ChannelHandlerContext ctx, Object msg) { // do something }@Override public void channelActive(final ChannelHandlerContext ctx) { // do something }@Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // do

something }}

Page 20: Netty indroduction

May 1, 2023 20

ChannelHandlerContextan association between a ChannelHandler and a ChannelPipeline.

it is created whenever a ChannelHandler is added to a ChannelPipeline.

Channel ChannelHandler ChannelHandler ChannelHandler

ChannelHandlerContext ChannelHandlerContext ChannelHandlerContext

ChannelPipeline

Channel bound to pipeline

Pipeline bound to Channel containing

Handlers

Context created when adding Handler to Pipeline

Page 21: Netty indroduction

May 1, 2023 21

IP Address FilterNetty can filter connections by IP address and subnet mask.

Example:

RuleBasedIpFilter.class: This class allows one to filter new connections based on the IpFilterRules. If no rules are provided, all connections will be accepted.

IpSubnetFilterRule.class: Use this class to create rules for RuleBasedIpFilter that group IP addresses into subnets. Supports both, IPv4 and IPv6.

ChannelPipeline pipeline = ch.pipeline();pipeline.addLast(new RuleBasedIpFilter(new IpSubnetFilterRule("192.168.20.113",32,IpFilterRuleType.REJECT)));

Page 22: Netty indroduction

May 1, 2023 22

Security IssueSecuring Netty applications with SSL/TLS o Use SslHandler.class doing decryption and encryption

SslHandlerEncrypted Decrypted Inbound

PlainEncryptedOutbound

1. Encrypted inbound data is intercepted by the SslHandler

2. The SslHandler decrypts the data and directs it inbound

3. Outbound data is passed through the SslHandler

4. The SslHandler encrypts the data and passes it outbound

Page 23: Netty indroduction

May 1, 2023 23

Adding SSL/TSL support(Mutual SSL Authentication)

public class SecureServerInitializer extends ChannelInitializer<SocketChannel> { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline();

String password = "password";

KeyStore ks = KeyStore.getInstance("JKS"); ks.load(ClassLoader.class.getResourceAsStream(File.separator + "netty_server.jks"), password.toCharArray());

TrustManagerFactory tmFactory = TrustManagerFactory.getInstance("SunX509"); tmFactory.init(ks);

KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(ks, password.toCharArray());

SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(kmf.getKeyManagers(), tmFactory.getTrustManagers(), null);

SSLEngine sslEngine = sslContext.createSSLEngine(); sslEngine.setUseClientMode(false); sslEngine.setNeedClientAuth(true);

pipeline.addFirst("SSL", new SslHandler(sslEngine));

}

Adds the SslHandler to the pipeline as the first handler

Page 24: Netty indroduction

May 1, 2023 24

Set SSLEngine SSLEngine sslEngine = sslContext.createSSLEngine();sslEngine.setUseClientMode(false);sslEngine.setNeedClientAuth(true);

sslEngine.setEnabledProtocols(sslEngine.getSupportedProtocols());sslEngine.setEnabledCipherSuites(sslEngine.getSupportedCipherSuites());sslEngine.setEnableSessionCreation(true);

Page 25: Netty indroduction

May 1, 2023 25

Building Netty HTTP/HTTPS applications HTTP is based on a request/response pattern: the client sends an HTTP request to the server, and the server sends back an HTTP response.

Netty provides a variety of encoders and decoders to simplify working with this protocol.

Example: public class HttpServerPipelineInitializer extends ChannelInitializer<Channel> { private final boolean client;

public HttpServerPipelineInitializer(boolean client) { this.client = client; }

@Override protected void initChannel(Channel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();

pipeline.addLast("decoder", new HttpRequestDecoder());pipeline.addLast("encoder", new HttpResponseEncoder());pipeline.addLast("codec", new HttpServerCodec());pipeline.addLast("aggregator", new HttpObjectAggregator(512 *

1024));pipeline.addLast("compressor", new HttpContentCompressor());

}}

Adds HttpObjectAggregator with a max message size of 512 KB to the pipeline

Automatically compressing HTTP messages

Page 26: Netty indroduction

May 1, 2023 26

Serialization via Protocol Buffers

public class SecureServerInitializer extends ChannelInitializer<SocketChannel> {

private final SslContext sslCtx;

public SecureServerInitializer(SslContext sslCtx) { this.sslCtx = sslCtx; }

@Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline();

pipeline.addFirst(sslCtx.newHandler(ch.alloc()));

// Add protobuf pipeline.addLast(new ProtobufVarint32FrameDecoder()); pipeline.addLast(new ProtobufVarint32LengthFieldPrepender()); pipeline.addLast(new ProtobufDecoder(PROTO_JAVA_INSTANCE)); pipeline.addLast(new ProtobufEncoder());

// and then business logic. pipeline.addLast(new SecureServerHandler()); }}

Adds Protobuf-Varint32Frame- Decoder to break down frames

Adds ProtobufEncoder to handle encoding of messages

Adds ProtobufDecoder to decode messages