本文知识点:
- Netty框架的作用
- Netty框架体系结构
- Netty框架Channel、ChannelHandler、Future、事件详解
前言
Netty框架是什么?Netty是一款用于快速开发高性能的网络应用程序的Java框架。它封装了网络编程的复杂性,使网络编程和Web技术的最新进展能够被 比以往更广泛的开发人员接触到。它不只是一个接口和类的集合,还定义了一种架构模型和一套丰富的设计模式。通过Netty框架开发人员可以编写更高效的、可复用的、可维护的代码。
Netty 体系结构
使用Netty可以比直接使用底层的Java API容易使用;在之前讲网络I/O的文章中讲过Java BIO 与Java NIO;Java NIO使用了事件驱动模型;相比于BIO单线程可以支持更多的连接,并且NIO是异步的,对于数据读取、连接、监听是无阻塞的。Netty且有Java NIO的这些特性,并且比Java NIO有更好的性能和更易用的API。
Netty的核心组件与Java NIO基本相同:
- Channel
- ChannelHandler
- Future
- 事件
Channel
在讲Java NIO时也有讲过Channel;在Java NIO中Channel的作用相当于一个通道,承载着数据的读与写以及4大事件。在Netty框架中Channel基本相同,它是Netty中可以代表一个硬件设备、一个文件、一个网络Socket或者一个可执行文件或者多个不同的I/O操作组件,它承载着读写操作。
ChannelHandler
一个ChannelHandler可以简单的理解为一个回调方法,在Netty内部使用回调来处理事件;当一个事件被触发时,与事件相关的ChannelHandler将被调用来响应这个事件的处理,下面可以通过一个服务端的示例来理解ChannelHandler的作用:
public class ConnectHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception{
System.out.println("Client :"+ctx.channel().remoteAddress() + " connected.");
}
}
当有一个客户端连接服务端后,服务端的Netty内部将有产生一个连接的事件,事件将触发ConnectHandler的回调触发。
Future
在Netty中,Future提供了一种在操作完成时通知应用程序的方式。这个对象可以看作是一个异步操作结果的占位符;它将在未来某个时刻完成并提供对结果的访问。Netty框架提供了ChannelFuture,它是一个Netty自己实现的Future,继承自JDK的java.util.concurrent.Future。
ChannelFuture接口额外提供了注册一个或者多个GenericFutureListener实例的方法,监听器的回调方法operationComplete()
将会在对应的操作完成时被调用。下面通过一个示例来说明:
EventLoopGroup workerGroup = new NioEventLoopGroup();
try{
Bootstrap b=new Bootstrap();
b.group(workerGroup);
b.channel(NioSocketChannel.class);
ChannelFuture f=b.connect("127.0.0.1","8080").sync();
//注册一个ChannelFutureListener以便在操作完成时获取通知
f.addListener(new ChannelFutureListener(){
@Override
public void operationComplete(ChannelFuture future){
if(future.isSuccess()){
ByteBuf buffer=Unpooled.copiedBuffer("Hello XXX.",Charset.defaultCharset());
future.channel().writeAndFlush(buffer);
}else{
future.cause().printStackTrace();
}
}
});
}finally{
workerGroup.shutdownGracefully();
}
ChannelHandler和Future是相互补充的机制;它们相互结合使用构成了Netty本身的关键构件之一。
事件
Netty的核心之一,事件用于触发ChannelHandler。在网络中通常会有入站与出站的流量,在Netty中也将事件按入站与出站进行了分类。通过这些不同的事件分类可以清晰的当前网络中有哪些动作发生并对这些动作做出响应。可以记录日志、对数据做转换、对流进行控制和应用程序的业务逻辑处理等。
入站事件:
- 连接已经激活或者连接失活
- 数据读取
- 用户事件
- 错误事件
出站事件:
- 打开或者关闭远程连接
- 将数据写到或者冲刷到网络Socket
入站与出站中的事件都可以对应到ChannelHandler中进行处理;这实现了一个完善的事件驱动范式。下面通过一张图来理解这些入站与出站中的事件:
ChnnelHandler为入站与出站处理器提供了基本的抽象,在Netty框架中提供了大量开箱即用的ChannelHeandler;如Http、SSL/TLS等。
Java NIO 与Netty
Java NIO的三大组件为Channel、Selector、Buffer;在Netty中只看到了Channel与Buffer;但Netty中也有Selector;只是Netty对Selector进行了包装,对应的包含类为EventLoop;EventLoop在Netty中的作用就如Selector在Java NIO中的作用。
在Netty中不需要开发者再写分发的模板代码,通过封装增加了框架接口的易用性,使用接口在使用上更加紧凑。