通过源码去认知Netty-io.netty.channel

目录

目标

源码版本 

io.netty.channel

Channel

what

提供一个用户试图

所有IO操作都是异步的

结构化 parent

支持向下转型down-cast

释放资源

ChannelId

Channel的全局唯一标示

相关因素

ChannelHandler

what

开发者需要做什么

ChannelHandlerContext引用的作用

信息存储

@Sharable

子类ChannelInboundHandler

子类ChannelOutboundHandler

DefaultChannelHandlerContext

ChannelPipeline

what

与channel的关系

结构图示

addLast方法

如何避免handler阻塞

事件传递

ChannelPipeline应包含三类的ChannelHandler

随时添加handler

子类DefaultChannelPipeline

pipeline中主要field tail

pipeline中主要field head

ChannelFuture

what

状态

addListener好于await

IO操作超时与await超时是没有关系的

EventLoop

what

类层次图示

eventLoop与eventLoopGroup的关系

MultithreadEventLoopGroup

SingleThreadEventLoop

io.netty.bootstrap

NIO封装


目标

通过io.netty.channel和io.netty.bootstrap两个package,对netty进行总体认知。进一步查看netty对NIO的封装,了解源码实现,梳理类层次关系与源码流程。

源码版本 

Netty v4.1.5

io.netty.channel

Channel

what

Channel作为网络socket或IO组件的连接体。

extends AttributeMap, ChannelOutboundInvoker, Comparable

io操作需要通过channel发起,所以继承了outbound.

提供一个用户试图

  •         channel的状态,如open/connected
  •         channel的配置
  •         channel支持的IO操作
  •         channelpipeline,处理与该channel相关的所有IO事件/请求

所有IO操作都是异步的

        所有IO操作都会立即返回,且返回channelFuture,当IO已经完成时,会notify该future。

结构化 parent

        指明该channel时如何被创建的

支持向下转型down-cast

        用来支持特殊传输操作,因为某些传输实现拥有特有的操作。

释放资源

        close时,确保释放所有资源

ChannelId

Channel的全局唯一标示

相关因素

  • 物理地址MAC address/网络适配器the network adapter
  • 当前进程ID
  • System.currentTimeMillis()
  • System.nanoTime()
  • 随机32bit整数
  • 顺序生成的32bit整数

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

DefaultChannelHandlerContext

channelHandler的上下文,对channelHandler进行包装。

private final ChannelHandler handler

通过源码去认知Netty-io.netty.channel_第1张图片

ChannelPipeline

what

包含由多个ChannelHandler组成的双向链表,用来控制与Channel相关的IO事件与操作。ChannelPipeline实现了一个起到拦截过滤作用的结构,让用户可以充分控制如何处理事件,handler间如何交互。

与channel的关系

Channel:ChannelPipeline=1:1

当Channel创建时,会自动创建ChannelPipeline

结构图示

通过源码去认知Netty-io.netty.channel_第2张图片

图来自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对应方法,

ChannelFuture

what

在Netty中所有IO操作都是异步的。可以通过返回的ChannelFuture来获取执行结果或状态信息。

状态

ChannelFuture两个终态,未完成与完成。完成态分为:成功,失败,取消。
得到ChannelFuture后,可等待完成,也可添加addListener(当操作完成时会notify)

两种终态的图示,来自netty java源码

通过源码去认知Netty-io.netty.channel_第3张图片

addListener好于await

addListener是非阻塞的;await是阻塞IO Thread。
确保不要在IO Thread中调用await(),可以使用await(timeout),否则可能导致dead lock,会抛出BlockingOperationException。

IO操作超时与await超时是没有关系的

IO超时,future将是failure的。IO超时需要配置,而不是通过await控制。

EventLoop

what

负责event(轮询)发现与event执行

类层次图示

通过源码去认知Netty-io.netty.channel_第4张图片

eventLoop与eventLoopGroup的关系

  • eventLoopGroup通过eventExcuter[]来引用多个eventLoop;构造函数中nThreads即为数组大小。
  • eventLoopGroup创建的同时会创建一个Excutor,创建nThreads个eventLoop,且均由该excutor进行调度。
  • 默认excutor为ThreadPerTaskExecutor,会为每个task创建一个thread,这也太奢侈了。

MultithreadEventLoopGroup

其管理的eventloop共享一个executor

SingleThreadEventLoop

 

 

io.netty.bootstrap

自由门

 

NIO封装

自由门

 

你可能感兴趣的:(RPC)