前言
本篇主要讲解Netty
的六大组件Handler, Pipeline, EventLoop, TaskQueue, Future和Promise
Future 和 Promise
Netty
中的Future
继承于jdk
的Future
, Promise
是对Netty
中的Future
的扩展
jdk
中的Future
只能同步等待任务结束才能得到结果Netty
中的Future
可以同步等待任务结束得到结果, 也可以异步方式得到结果, 但是都要等待任务结束Netty
中的Promise
不仅有Netty - Future
的功能 而且脱离了任务独立存在,只作为两个线程之间传递结果的容器
Netty Future
Netty
中的Future
可以通过EventLoop.submit()
方法来获取
- 可以通过
get()
方法来阻塞的获取结果 - 可以通过
getNow()
方法非阻塞的获取结果, 没有结果则为null
- 可以通过
future.addListener()
方法, 在Callable
方法执行的线程中, 异步获取返回结果
Netty Promise
Promise
相当于一个容器, 可以用户存放各个线程中的结果, 然后让其他线程去获取该结果
ChannelHandler
在Netty
中, ServerHandler
和ClientHandler
存在如下关系
- 都继承于
ChannelInboundHandlerAdapter
ChannelInboundHandlerAdapter
继承于ChannelHandlerAdapter
ChannelHandlerAdapter
实现了ChannelHandler
因此在Netty
中不论是客户端还是服务端的Handler
都可以称之为ChannelHandler
在Netty
中的ChannelHandler
的作用是将当前ChannelHandler
的 IO事件 进行处理并传递给同一个ChannelPipeline
中的下一个ChannelHandler
, 因此在同一个ChannelPipeline
中的ChannelHandler
就形成了一个责任链
inbound
是入站, 客户端到服务端是出站outbound
是出站, 服务端到客户端
数据在基于
Netty
的服务器或客户端中的处理流程:
- 读取数据
- 解码数据
- 处理数据
- 编码数据
- 发送数据 其中每个过程都会用到
ChannelHandler
责任链网络异常,图片无法展示|
Netty Pipeline
每一个Channel
中都包含了一个ChannelPipeline
, 每个ChannelPipeline
中又包含了一个由ChannelHandlerContext
构成的双向链表, 在ChannelHandlerContext
中又包含了一个ChannelHandler
Channel
和ChannelPipeline
相互引用
入站和出站
- 当有入站操作的时候, 会从
头
开始向后调用Handler
, 直到Handler
不是处理Inbound
操作为止 - 当有出站操作的时候, 会从
尾
开始向前调用Handler
, 直到Handler
不是处理OutBound
操作为止
EventLoop 组件
事件循环对象EventLoop
的本质是一个单线程执行器, 如果追踪他的继承链, 就会发现该类是继承于JUC
的Executor
, 同时每一个EventLoop
都维护了一个Selector
实例, Selector
实例会监听注册在其上Channel
的 IO事件
- 一个
Selector
实例上会注册多个Channel
关于EventLoop
组件, 我之前专门出过一篇文章, 从简单分析到源码阅读, 可以去看Netty「源码阅读」之 EventLoop 简单介绍到源码分析 - 掘金 (juejin.cn)
TaskQueue
在Netty
中的NioEventLoop
有两个重要的属性, 分别是Selector
和TaskQueue
, 在之前我专门写过文章写过Selector
在上面, 我们讲解了会在Pipline
中调用Handler
来处理我们的业务, 那么假如在某一个Handler
有一个长时间的操作, 这就势必会造成Pipline
的阻塞, 这时我们就可以将这个耗时的处理提交到TaskQueue
进行异步的执行
三种使用场景
- 处理用户程序的自定义普通任务的时候
- 处理用户程序的自定义定时任务的时候
- 非当前
Reactor
线程调用当前Channel
的各种方法的时候
结束
通过本次讲解, 我们对于Netty
的六大组件都有了基本的了解, 再配合我们之前的文章, 就对Netty
框架的整体架构, 运行流程都有了大概的了解