我是靠谱客的博主 稳重大碗,最近开发中收集的这篇文章主要介绍通过源码去认知Netty-io.netty.channel1. 目标2. 源码版本 3. io.netty.channel4. io.netty.bootstrap5. NIO封装,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

目录

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封装所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(79)

评论列表共有 0 条评论

立即
投稿
返回
顶部