Netty是由JBoss开发,基于Java NIO的一个高性能通信框架。之前几篇文章介绍了Java NIO的一些基本的概念和API。但在实际的网络开发中,其实很少使用Java NIO原生的API。主要有以下原因:
在《Netty权威指南》这本书里提到一个真实的故事,两个项目团队都要做基于NIO非阻塞特性的一个高性能、异步和高可靠性的底层通信框架,但一个团队选择了基于Java NIO API从头开发,另一个团队选择了基于Netty开发。最终,从头开发的团队遇到了各种各样的问题,导致项目延迟,而基于Netty开发的团队则进展顺利。
其实网络开发是一个比较复杂的事情,因为网络的不稳定性,通常会遇到各种各样的问题,比如前面提到的客户端突然断连、TCP的拆包和沾包等等。
幸运的是,网络上已经有了这么一个成熟的框架帮我们处理了这些事情,这个框架就是Netty。Netty主要应用于以下领域:
这里有一个Netty的功能特性的图:

Netty Core提供了基本功能,包括文件零拷贝、基本的API、可扩展的基于事件的模型(下文详细介绍)。
Netty支持非常多的协议,比如HTTP、WebSocket等。当然,Netty也可以自定义协议。常见协议的示例代码可以参考netty源码里面的example包。
Netty同时支持Java的BIO和NIO两种方式。且很容易与Spring等主流框架进行集成。
首先介绍处理事件的两种方式:
Reactor是反应堆的意思。Reactor线程模型是指通过一个或多个输入,同时传递给服务处理器的服务请求的事件驱动处理模式。
Reactor模式主要工作原理如下图:

Reactor 有一个专门负责监听和分发事件的线程,如图中的Service Handler,所有请求进来后,被它分发到具体的处理线程,如图中的Event Handler去处理。
Reactor可能有多个,而Netty正是使用了多Reactor的线程模型。

Netty里面有两个Group,分别是Boss Group和Worker Group。其中,Boss Group用于处于连接,Worker Group用于处理实际的读写IO。
Boss Group里面的NioEventLoop会轮询accept事件,遇到有新的连接,就生成NioSocketChannel,并把这个Channel注册到Worker Group的Selector上。
Worker Group轮询read和write事件,在可读或者可写条件满足时,就进行处理。
Worker Group和Boss Group都是通过里面的NioEventLoop来操作的。NioEventLoop中维护了一个线程和任务队列,支持异步提交执行任务,线程启动时会调用NioEventLoop的run方法。
最后都会执行一个runAllTasks方法,它用于处理任务队列中的任务。任务队列中的任务包括用户调用 eventloop.execute或schedule执行的任务,或者其他线程提交到该eventloop的任务。
以下是使用Netty创建一个Server的示例代码。Client也可以使用Netty来创建,也可以使用之前文章里面的NIO示例代码。这里就不展示基于Netty的Client端的代码,只展示Server端的代码了。
public class Server {
private final static int PORT = 8080;
public static void main(String[] args) {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 1024)
.childHandler(new ChildChannelHandler());
ChannelFuture f = b.bind(PORT).sync();
System.out.println(Thread.currentThread().getName() +
",服务器开始监听端口,等待客户端连接.........");
f.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
private static class ChildChannelHandler extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(new ServerHandler());
}
}
static class ServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf buf = (ByteBuf) msg;
byte[] reg = new byte[buf.readableBytes()];
buf.readBytes(reg);
String body = new String(reg, StandardCharsets.UTF_8);
System.out.println(Thread.currentThread().getName() +
",The server receive order : " + body);
String respMsg = "I am Server,消息接收 success!";
ByteBuf respByteBuf = Unpooled.copiedBuffer(respMsg.getBytes());
ctx.write(respByteBuf);
}
}
}
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/359/viewspace-2823258/ ,如需转载,请注明出处,否则将追究法律责任。