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一个连接一个线程模型,架构的性能、弹性伸缩能力和可靠性都得到了极大的提升。
Buffer:传统I/O是顺序地从一个Stream中读取一个或多个字节,不能随意改变读取指针的位置。在NIO中,抛弃了传统的I/O流,而是引入了Channel和Buffer的概念。在NIO中,只能从Channel中读取数据到Buffer中或将数据从Buffer中写入到Channel。可以读取任意位置的数据。
线程模型:
读取之后的编解码在那个线程中进行?编解码后的消息如何派发?
Netty线程模型:主要基于主从Reactors多线程模型做了一些修改
异步处理:
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>() {
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();
}
}
.Sharable
class EchoClientHandler extends SimpleChannelInboundHandler<ByteBuf> {
public void channelActive(ChannelHandlerContext ctx) throws Exception {
ctx.writeAndFlush(Unpooled.copiedBuffer("Netty rocks!", CharsetUtil.UTF_8));
}
protected void channelRead0(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
System.out.println("Client received:"+ in.toString(CharsetUtil.UTF_8));
}
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>() {
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();
}
}
.Sharable
class EchoClientHandler extends SimpleChannelInboundHandler<ByteBuf> {
public void channelActive(ChannelHandlerContext ctx) throws Exception {
ctx.writeAndFlush(Unpooled.copiedBuffer("Netty rocks!", CharsetUtil.UTF_8));
}
protected void channelRead0(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
System.out.println("Client received:"+ in.toString(CharsetUtil.UTF_8));
}
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}