netty系列(五)IdleStateHandler和IdleStateHandlerEventState

笔记:IdleStateHandler是netty自带的,而idleStateHandlerEventState是我们自己实现的一个inboundHandler,任何一个实现了userTriggerEvent事件的InBound都可以接收和处理IdleStateHandler事件。

简单概括IdleStateHandler的流程:很简单,就是ctx包含了channel对应的eventloop,所以在IdleStateHandler就是在handlerAdded事件或者channelActive事件中往channel对应的eventloop中丢几个scheduledTask即定时任务,当定时任务运行的时候一旦检测到超时时间,就通过ctx.fireUserEventTrigger函数往pipeline丢一个UserEventTrigger事件。这个定时任务的检测也比较简单:对于读超时,idleStateHandler初始化时记录一次状态,然后运行时会在channelRead函数中记录一个原子变量ReadIng表示当前正在读,然后在ChannelReadComplete中记录一个变量:lastReadTime表示最后一次读操作完成的时间,然后定时任务就是检测当前时间-lastReadTime是否超过了阈值,如果超过了就通过fireUserEventTrigger往pipeline丢一个userEventTrigger事件。对于写超时,也是一样的流程,只不过略有区别:读操作是有一个专门的读完成事件即ChannelReadComplete,但是写没有,因为写是异步的,所以他会返回一个promise而promise可以添加Listener即监听operatorComplete事件,在责怪listener里面就可以设置当前的事件为lastWriteTime,然后写超时定时任务执行的时候就会检测是否超时了,如果超时就会发送超时事件(即userEventTrigger)到pipeline。因为不管是读还是写还是all,超时任务运行一次就结束了,所以运行结束之前还要再往scheduledTaskQueue里面塞下一个超时任务,

换个方式解释下:

每个channel都对应一条流水线,不同的channel使用不同的流水线(即channel继承了AbstractChannel基类,然后AbstractChannel内部含有一个pipeline变量,所以每创建一个channel,都会创建pipeline对象,即),也就是说不同的channel使用不同的idlestatehandler,每个channel都含有一个ctx,每个channel建立的时候都会调用一遍IdleStateHandler的handleAdded方法,handleAdded方法中又调用了initialize方法,然后initialize方法就会针对这个channel创建一个定时任务,这个定时任务包含了这个channel对应的ctx对象,然后把这个定时任务丢到idleHandler的异步线程去,这样这个异步线程一旦检查到超时事件,就会fireUserEvent到流水线

代码流程:

直接从handlerAdded或者channelActive开始。如果handlerAdded时channel还没准备好,那么就在channelActive事件中处理

broker 复制代码
1:channelReadComplete事件
IdleStateHandler.handlerAdded                #第一步是向eventLoop添加定时任务
  IdleStateHandler.initialize                #添加任务到eventloop的scheduledTaskQueue(定时任务队列)
    lastReadTime=lastWriteTime=now()         #初始化lastReadTime和lastWriteTime为当前时间
    if readTimeOut>0:                        #如果设置了读超时时间
      rtask=new ReaderIdleTimeoutTask        #创建一个读超时任务
        ReaderIdleTimeOutTask.run   
          nextDelay -= ticksInNanos() - lastReadTime #nextDelay<0表示超时
          IdleStateHandler.schedule          #往eventloop的定时任务队列塞进去下一次的超时任务
          if nextDelay<0:                    #如果本次超时任务检测到了超时 
            pipeline.fireUserEventTrigger    #把超时事件丢到pipeline,由对应的handler的UserEventTrigger进行处理
      IdleStateHandler.schedule(rtask)       #把读超时任务丢到eventloop的scheduledTaskQueue

    if writeTimeOut>0:                       #如果设置了写超时时间
      wtask=new WriterIdleTimeoutTask        #创建一个写超时任务
        WriterIdleTimeoutTask.run
          change=WriterIdleTimeoutTask.hasOutputChanged #检测输出缓冲区是否发生了变化
            1:检测是否有write操作
            2:检测是否有flush操作
            3:检测输出缓冲区是否发生了变化。就是对缓冲区做一次hash
          if nextDealy<0&&change:            #如果检测到了写空闲超时时间就发送UserEventTrigger
            pipeline.fireUserEvetnTrigger    #!!不同的event有不同的类型,所以UserEventTriggerHandler可以
          IdleStateHandler.schedule            #往eventloop的定时任务队列塞进去下一次的超时任务
      IdleStateHandler.schedule(wtask)   #把写超时任务丢到eventloop的scheduledTaskQueue

    if allTimeOut>0:                     #如果设置了all超时时间即读写
      alltask=new AllIdleTimeoutTask     #创建一个all超时任务
        AllIdleTimeoutTask.run           #就是既检测读也检测写
      IdleStateHandler.schedule(alltask) #把all超时任务丢到eventloop的scheduledTaskQueue

2:channelReadComplete
IdleStateHandler.channelReadComplete
  lastReadTime = time.now                #重置lastReadTime
  reading = false;                       #重置reading,reading=true表示读取流程还没处理完
  ctx.fireChannelReadComplete();         #继续传递readComplete事件


3:write。write/connect这些都是由外到内的动作,所以都是异步,通过promise来处理
IdleStateHandler.write
  ChannelFuture promise=ctx.write   
  ChannelFuture.addListener              #在operationComplete事件中重置写超时变量即lastWriteTime
相关推荐
栗筝i18 分钟前
Maven 中的依赖管理机制
java·maven
Conmi·白小丑19 分钟前
Conmi的正确答案——Maven加载时检测到的漏洞修复
java·maven
雪球不会消失了27 分钟前
06-RabbitMQ基础
java·网络·spring cloud·mq
web1309332039830 分钟前
东方通TongWeb替换Tomcat的踩坑记录
java·tomcat
xmh-sxh-131436 分钟前
ActiveMQ支持哪些传输协议
java
@泽栖36 分钟前
项目引入MybatisPlus
java·后端·mybatis
夜半无声1 小时前
spring boot 多数据源集成mysql、postgresql、phoenix、doris等
java·spring boot·后端
小猪佩奇TONY1 小时前
Vulkan 学习(12)---- Vulkan pipeline 创建
java·学习·spring
DC_BLOG2 小时前
数据结构排序
java·数据结构·算法·排序算法