概述
目录
1. 目标
2. 源码版本
3. io.netty.channel
3.1. Channel
3.2. ChannelId
3.3. ChannelHandler
3.4. DefaultChannelHandlerContext
3.5. ChannelPipeline
3.6. ChannelFuture
3.7. EventLoop
3.8. MultithreadEventLoopGroup
3.9. SingleThreadEventLoop
4. io.netty.bootstrap
5. NIO封装
1. 目标
通过io.netty.channel和io.netty.bootstrap两个package,对netty进行总体认知。进一步查看netty对NIO的封装,了解源码实现,梳理类层次关系与源码流程。
2. 源码版本
Netty v4.1.5
3. io.netty.channel
3.1. Channel
what
Channel作为网络socket或IO组件的连接体。
extends AttributeMap, ChannelOutboundInvoker, Comparable<Channel>
io操作需要通过channel发起,所以继承了outbound.
提供一个用户试图
- channel的状态,如open/connected
- channel的配置
- channel支持的IO操作
- channelpipeline,处理与该channel相关的所有IO事件/请求
所有IO操作都是异步的
所有IO操作都会立即返回,且返回channelFuture,当IO已经完成时,会notify该future。
结构化 parent
指明该channel时如何被创建的
支持向下转型down-cast
用来支持特殊传输操作,因为某些传输实现拥有特有的操作。
释放资源
close时,确保释放所有资源
3.2. ChannelId
Channel的全局唯一标示
相关因素
- 物理地址MAC address/网络适配器the network adapter
- 当前进程ID
- System.currentTimeMillis()
- System.nanoTime()
- 随机32bit整数
- 顺序生成的32bit整数
3.3. ChannelHandler
what
处理IO事件/IO操作,并传递给下一个handler。
开发者需要做什么
开发者需要实现channelHandler具体实现类
- ChannelInboundHandler处理IO事件
- ChannelOutboundHandler处理IO操作
- 更方便的方式:实现对应的适配器。
- ChannelInboundHandlerAdapter处理IO事件
- ChannelOutboundHandlerAdapter处理IO操作
- ChannelDuplexHandler处理IO事件与操作
ChannelHandlerContext引用的作用
handler通过context的引用,才可以与其所归属的pipeline进行交互。
信息存储
当channelHandler需要存储信息时,建议使用成员变量。因为信息是与channel相关的,所以为channel生成单独的handler实例。
如果想复用handler实例,请为handler使用注解@Sharable,请使用ChannelHandlerContext提供的AttributeKey。
@Sharable
在handler上使用该注解,表示可以复用。否则不可复用,因为其已被标示为unshared。
子类ChannelInboundHandler
添加状态变化的回调方法 adds callbacks for state changes
- channelRegistered 注册到eventLoop
- channelUnregistered 从eventLoop解除注册
- channelActive 当前可用的
- channelInactive 不可用,生命周期终点
- channelRead 已经从远端节点读取到信息
- channelReadComplete 读操作获取的最后信息已经被channelRead消费掉。如果没有为channel设置自动读,则不会尝试读取inbound信息。
- userEventTriggered 用户注册的event已经触发
- channelWritabilityChanged channel的可写状态发生改变。可通过channel.isWritable进行检查。
- exceptionCaught 抛出异常
子类ChannelOutboundHandler
获取到IO outbound操作的notify通知
- bind 绑定操作发生时
- connect 连接操作发生时
- disconnect 断开连接操作发生时
- close
- deregister 从当前注册的eventloop中取消注册
- read 拦截context的read操作
- write 沿着pipeline进行写,当调用channel的flush时才会将信息输出
- flush
3.4. DefaultChannelHandlerContext
channelHandler的上下文,对channelHandler进行包装。
private final ChannelHandler handler
3.5. ChannelPipeline
what
包含由多个ChannelHandler组成的双向链表,用来控制与Channel相关的IO事件与操作。ChannelPipeline实现了一个起到拦截过滤作用的结构,让用户可以充分控制如何处理事件,handler间如何交互。
与channel的关系
Channel:ChannelPipeline=1:1
当Channel创建时,会自动创建ChannelPipeline
结构图示
图来自netty java文件
inbound事件,handler处理顺序为从下到上。
outbound事件,handler处理顺序为从上到下。
注意:inbound data的生成与outbound data的操作,均是由netty内部的IO线程完成的。
addLast方法
addLast方法是把handler加在上层,既tail。
如何避免handler阻塞
如果handler处理时间较长,为避免IO Thread被block,在添加Handler时可以启用EventExecutorGroup。
如果handler是异步的或快速的,可以不考虑group。
事件传递
handler通过调用ChannelHandlerContext的事件传播方法完成事件传递。
ChannelPipeline应包含三类的ChannelHandler
- Protocol Decoder:二进制数据转换为java object
- Protocol Encoder:java object转换为二进制
- Business Logic Handler:执行业务逻辑
随时添加handler
线程安全的,任何时间都可从ChannelPipeline中添加或删除ChannleHanler
子类DefaultChannelPipeline
// 双向链表
final AbstractChannelHandlerContext head;
final AbstractChannelHandlerContext tail;
pipeline中主要field tail
final class TailContext extends AbstractChannelHandlerContext implements ChannelInboundHandler
作用:作为最后一个inboundHandler存在,主要任务是release msg,引用数refenrence count减一,当引用数为0时销毁msg。
pipeline中主要field head
final class HeadContext extends AbstractChannelHandlerContext
implements ChannelOutboundHandler, ChannelInboundHandler
作用:作为第一个intboundHandler存在,作为最后一个outboundHandler存在。
将hanler和IO event与操作衔接在一起。例如写请求,经过一系列outboundHandler处理后到达这里,再由其调用对应channel的unsafe的方法进行与jdkNIOChannel的操作。读事件,首先调用channel的unsafe对应方法,
3.6. ChannelFuture
what
在Netty中所有IO操作都是异步的。可以通过返回的ChannelFuture来获取执行结果或状态信息。
状态
ChannelFuture两个终态,未完成与完成。完成态分为:成功,失败,取消。
得到ChannelFuture后,可等待完成,也可添加addListener(当操作完成时会notify)
两种终态的图示,来自netty java源码
addListener好于await
addListener是非阻塞的;await是阻塞IO Thread。
确保不要在IO Thread中调用await(),可以使用await(timeout),否则可能导致dead lock,会抛出BlockingOperationException。
IO操作超时与await超时是没有关系的
IO超时,future将是failure的。IO超时需要配置,而不是通过await控制。
3.7. EventLoop
what
负责event(轮询)发现与event执行
类层次图示
eventLoop与eventLoopGroup的关系
- eventLoopGroup通过eventExcuter[]来引用多个eventLoop;构造函数中nThreads即为数组大小。
- eventLoopGroup创建的同时会创建一个Excutor,创建nThreads个eventLoop,且均由该excutor进行调度。
- 默认excutor为ThreadPerTaskExecutor,会为每个task创建一个thread,这也太奢侈了。
3.8. MultithreadEventLoopGroup
其管理的eventloop共享一个executor
3.9. SingleThreadEventLoop
4. io.netty.bootstrap
自由门
5. NIO封装
自由门
最后
以上就是稳重大碗为你收集整理的通过源码去认知Netty-io.netty.channel1. 目标2. 源码版本 3. io.netty.channel4. io.netty.bootstrap5. NIO封装的全部内容,希望文章能够帮你解决通过源码去认知Netty-io.netty.channel1. 目标2. 源码版本 3. io.netty.channel4. io.netty.bootstrap5. NIO封装所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复