基本介绍:
- 异步的概念和同步相对。当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的组件在完成后,通过状态、通知和回调来通知调用者。
- Netty 中的 I/O 操作是异步的,包括 Bind、Write、Connect 等操作会简单的返回一个 ChannelFuture。
- 调用者并不能立刻获得结果,而是通过 Future-Listener 机制,用户可以方便的主动获取或者通过通知机制获得 IO 操作结果。
- Netty 的异步模型建立在 future 和 callback 的之上的。 callback 就是回调。 Future,它的核心思想是:假设一个方法 fun,计算过程可能非常耗时,等待fun返回显然不合适。那么可以在调用 fun 的时候,立马返回一个 Future, 然后可以通过Future去监控方法fun的处理过程(即:Future-Listenner 机制)
Feature说明:
- 表示异步执行结果,可以通过它提供的方法来检查执行是否完成
- ChannelFuture 是一个接口 public interface ChannelFuture extends Future<Void> 我们可以添加监听器,当监听的事件发生时,就会通知到监听器。
Pipeline 工作原理示意图:
说明:
- 在使用 Netty进行编程时,拦截操作和转换操作入栈的数据只需要您提供 callback 或 利用 future 即可。这使得链式操作简单、高效、并有利于编写可重用的、通用的代码。
- Netty 框架的目标就是让你的业务逻辑从网络基础应用编码中分离出来、解脱出来
Future-Listenner 机制:
当 Future 对象刚刚创建时,处于非完成状态,调用者可以通过返回的 ChannelFuture 来获取操作执行的状态、注册监听函数来执行完成后的操作
- 通过 isDone 方法来判断当前操作是否完成
- 通过 isSuccess方法来判断已完成的当前操作是否成功
- 通过 getCause 方法来获取已完成的当前操作失败的原因
- 通过 isCancelled 方法来判断已完成的当前操作是否被取消
- 通过 addListener 方法来注册监听器,当操作已完成(isDone 方法返回完成),将会通知执行的监听器
示例代码:
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
public class NettyServer {
public static void main(String[] args) throws InterruptedException {
// 创建两个线程组 boosGroup 和 workerGroup
// bossGroup 只处理连接请求, workerGroup 与客户端业务处理
// 两者皆是无限循环
// boosGroup 和 workerGroup 含有的子线程(NioEventLoop)的个数,默认实际 Cpu 核数 * 2
EventLoopGroup boosGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
// 创建服务器端的启动对象,配置启动参数
ServerBootstrap bootstrap = new ServerBootstrap();
// 使用链式编程进行设置
bootstrap.group(boosGroup, workerGroup) // 设置两个线程组
.channel(NioServerSocketChannel.class) // 使用NioServerSocketChannel 作为服务器通道实现
.option(ChannelOption.SO_BACKLOG, 128) // 设置线程队列等待连接的个数
.childOption(ChannelOption.SO_KEEPALIVE, true) // 设置保持活动连接状态
.childHandler(new ChannelInitializer<SocketChannel>() { // 创建一个通道初始化对象(匿名对象)
// 给pipeline 设置处理器
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(new NettyServerHandler());
}
}); // 给我们的workerGroup 的 EventLoop 对应的管道设置处理器
System.out.println("...... 服务器 is ready ...");
// 启动服务器,绑定一个端口并且同步,生成一个 channelFuture 对象
ChannelFuture cf = bootstrap.bind(9527).sync();
// 给cf 注册监听器,监听我们关心的事件
cf.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture channelFuture) throws Exception {
if(cf.isSuccess()) {
System.out.println("监听端口 9527 成功");
} else {
System.out.println("监听端口 9527 失败");
}
}
});
// 对关闭通道进行监听
cf.channel().closeFuture().sync();
} finally {
boosGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
小结:
相比传统阻塞 I/O, 执行 I/O 操作后线程会被阻塞住,直到操作完成;异步处理的好处是不会造成线程阻塞, 线程在 I/O 操作期间可以执行别的程序,在高并发情形下会更稳定和更高的吞吐量