netty 简介
netty 是一个利用java的高级网络的能力,隐藏了java背后的复杂性,封装了一个Api的客户端/服务端框架。netty 的高性能和可扩展性,可以作为你自己的独特的应用,让你更用心的花费时间在业务上。
netty 构成
-
Channel
Channel 是NIO基本结构,代表一个用于连接到实体组件,能够执行一个或多个不同I/O操作的开放连接,可以比喻为一个打开或者关闭,连接或者断开,且能够运输数据的管道。 -
Callback 回调
callback 通俗的说就是一个方法,作为引用传递给另一个方法,使其在某个合适的时间被调用,这种技术在各种编程语言中被采纳,例如jsfunction f (msg) { // 普通方法 console.info(msg); } function f2(msg, f) { // doString f(msg); } f2("hello world", f);// 一个方法的引用被传递
这种技术通常备用通知操作,在netty内部使用回调处理事件时,一但回调被触发,事件交由ChannelHeader 的实现类处理,
public class ConnectHandler extends ChannelInboundHandlerAdpter { @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { // 建立新的连接时被调用 // doString } }
-
Future
Future 提供了另一种通知应用的操作完成的方式,就是对象作为一个异步操作结果的占位符,它将在某个时候完成并提供结果。
接下来我们看看jdk自带的接口java.util.concurrent.Future.// 首先来看源码分析 public interface Future<V> { // 用来取消任务,如果任务取消成功返回true,任务取消失败,返回false。参数 mayInterruptIfRunning 表示是否允许取消正在执行的却没执行完毕的任务,如果设置成true,则表示可以取消正在执行过程中的任务。如果任务已经完成,则无论mayInterruptIfRunning为true还是false,此方法返回false。如果任务正在执行,若mayInterruptIfRunning 设置为true,则返回true;若 mayInterruptIfRunning 设置为false,则返回false;如果任务还没有执行,则无论mayInterruptIfRunning是true还是false,肯定返回true boolean cancel(boolean mayInterruptIfRunning); // 任务是否被取消成功,如果任务正常完成前被取消成功,则返回true boolean isCancelled(); // 任务是否已经完成,若完成,返回true boolean isDone(); // 用于获取执行结果,这个方法会产生阻塞,会一直等到执行结果完毕才返回 V get() throws InterruptedException, ExecutionException; // 获取执行结果,在制定时间内,还未取得到结果,则直接返回null V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
}
```
综上看来,Future 提供了三种功能:
- 判断任务是否完成
- 能够中断任务
- 能够获取任务执行结果
由于这是一个接口,无法直接创建对象使用,就有了FutureTask类,这里不具体展开,后续会出系列文档。但是这里已经看出了,提供的实现只是允许手动检测操作是否完成或阻塞,很麻烦,作为成熟的框架neety 肯定有封装,那就是 ChannelFuture,每个 Netty 的 outbound I/O 操作都会返回一个 ChannelFuture;这样就不会阻塞。这就是 Netty 所谓的“自底向上的异步和事件驱动”。
接下来看例子:
Channel channel = ...;
//不会阻塞
ChannelFuture future = channel.connect( //1 异步连接远程地址,调用立即返回并提供ChannelFuture
new InetSocketAddress("192.168.0.1", 25));
future.addListener(new ChannelFutureListener() { //2 操作完成后通知注册一个 ChannelFutureListener
@Override
public void operationComplete(ChannelFuture future) {
if (future.isSuccess()) { //3 检查操作的状态
ByteBuf buffer = Unpooled.copiedBuffer(
"Hello", Charset.defaultCharset()); //4 创建一个ByteBuf 来保存数据
ChannelFuture wf = future.channel().writeAndFlush(buffer); //5 异步发送数据到远程,再次返回ChannelFuture
// ...
} else {
Throwable cause = future.cause(); //6 如果有一个错误则抛出 Throwable,描述错误原因
cause.printStackTrace();
}
}
});
-
Event 和 Handler
-
整合
FUTURE, CALLBACK 和 HANDLER
Netty 的异步编程模型是建立在 future 和 callback 的概念上的。所有这些元素的协同为自己的设计提供了强大的力量。拦截操作和转换入站或出站数据只需要您提供回调或利用 future 操作返回的。这使得链操作简单、高效,促进编写可重用的、通用的代码。一个 Netty 的设计的主要目标是促进“关注点分离”:你的业务逻辑从网络基础设施应用程序中分离。
SELECTOR, EVENT 和 EVENT LOOP
Netty 通过触发事件从应用程序中抽象出 Selector,从而避免手写调度代码。EventLoop 分配给每个 Channel 来处理所有的事件,包括注册感兴趣的事件
调度事件到 ChannelHandler
安排进一步行动
该 EventLoop 本身是由只有一个线程驱动,它给一个 Channel 处理所有的 I/O 事件,并且在 EventLoop 的生命周期内不会改变。这个简单而强大的线程模型消除你可能对你的 ChannelHandler 同步的任何关注,这样你就可以专注于提供正确的回调逻辑来执行。该 API 是简单和紧凑。