vlambda博客
学习文章列表

Netty图文解析+代码Demo

https://juejin.im/post/5be00763e51d453d4a5cf289

netty是一个异步事件驱动的网络应用程序框架,

高性能主要依靠与I/O模型和线程处理模型

I/O模型:如何收发数据

线程处理模型:如何处理数据



可靠性能力补齐:通过代码补足框架运行中出现的一些问题(例如mq消息重复消费问题)

断连重连、网络闪断、半包读写、失败缓存、网络拥塞、异常码流



I/O:


netty的I/O线程NioEventLoop由于聚合了多路复用器Selector,可以同时并发处理成百上千个客户端连接。

当线程从某客户端Socket通道进行读写数据时,若没有数据可用时,该线程可用进行其他任务。

一个I/O线程可用并发处理N个客户端连接和读写操作,这从根本上解决了传统同步阻塞I/O一个连接一个线程模型,架构的性能、弹性伸缩能力和可靠性都得到了极大的提升。

Netty图文解析+代码Demo



Buffer:传统I/O是顺序地从一个Stream中读取一个或多个字节,不能随意改变读取指针的位置。在NIO中,抛弃了传统的I/O流,而是引入了Channel和Buffer的概念。在NIO中,只能从Channel中读取数据到Buffer中或将数据从Buffer中写入到Channel。可以读取任意位置的数据。



线程模型:


读取之后的编解码在那个线程中进行?编解码后的消息如何派发?

 

Netty线程模型:主要基于主从Reactors多线程模型做了一些修改 

Netty图文解析+代码Demo


异步处理:

Future、ChannelFuture

netty的io操作是异步的,所以调用者并不能立刻直接获取到调用结果,需要通过Future-Listener机制,获取io结果。


运行:

Bootstrap 是客户端程序的启动引导类,作用是配置整个Netty程序,串联各个组件,一个Netty应用通常由一个Bootstrap开始

ServerBootstrap是服务端启动引导类


代码Demo:

EchoServer.java

public class EchoClient { private final String host; private final int port;
public EchoClient(String host, int port){ this.host = host; this.port = port; }
public void start() throws Exception{ EventLoopGroup group = new NioEventLoopGroup(); try{ Bootstrap b = new Bootstrap(); b.group(group).channel(NioSocketChannel.class).remoteAddress(new InetSocketAddress(host, port)).handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new EchoClientHandler()); } }); ChannelFuture f = b.connect().sync(); f.channel().closeFuture().sync(); }catch(Exception e){ e.printStackTrace(); }finally { group.shutdownGracefully().sync(); } }
public static void main(String[] args) throws Exception{ String host = "127.0.0.1"; int port = Integer.parseInt("8880"); new EchoClient(host, port).start(); }}
@ChannelHandler.Sharableclass EchoClientHandler extends SimpleChannelInboundHandler<ByteBuf> { @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { ctx.writeAndFlush(Unpooled.copiedBuffer("Netty rocks!", CharsetUtil.UTF_8)); }
@Override protected void channelRead0(ChannelHandlerContext ctx, ByteBuf in) throws Exception { System.out.println("Client received:"+ in.toString(CharsetUtil.UTF_8)); }
@Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); }}

EchoClient.java

public class EchoClient { private final String host; private final int port;
public EchoClient(String host, int port){ this.host = host; this.port = port; }
public void start() throws Exception{ EventLoopGroup group = new NioEventLoopGroup(); try{ Bootstrap b = new Bootstrap(); b.group(group).channel(NioSocketChannel.class).remoteAddress(new InetSocketAddress(host, port)).handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new EchoClientHandler()); } }); ChannelFuture f = b.connect().sync(); f.channel().closeFuture().sync(); }catch(Exception e){ e.printStackTrace(); }finally { group.shutdownGracefully().sync(); } }
public static void main(String[] args) throws Exception{ String host = "127.0.0.1"; int port = Integer.parseInt("8880"); new EchoClient(host, port).start(); }}
@ChannelHandler.Sharableclass EchoClientHandler extends SimpleChannelInboundHandler<ByteBuf> { @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { ctx.writeAndFlush(Unpooled.copiedBuffer("Netty rocks!", CharsetUtil.UTF_8)); }
@Override protected void channelRead0(ChannelHandlerContext ctx, ByteBuf in) throws Exception { System.out.println("Client received:"+ in.toString(CharsetUtil.UTF_8)); }
@Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); }}