00:00
我们先看read idol timeout task,它怎么去run,因为这是核心吗?我们不就是一个心跳检测吗?肯定他在这地方会不断的运行,说他这有个wrong方法。啊,有个run方法,我们来看一下他在做什么事情,那同学们我们一起来。阅读一下这个源码。阅读一下这个源码。嗯。大家看。大家看这里,首先他得到用户设置的超时时间。OK,超时时间拿到以后呢,下一步如果读读取操作结束了,就是说嗯,什么时候算是结束呢?就是我们那个handler的channel read completely这个方法设置了,就用当前时间减去给定时间和最后一次读操作时间。好,如果小于零。就触发事件,反之继续放入队列。间隔时间是新的计算时间。
01:05
这个呢,大家可能听起来是有点绕了啊,有点绕,我们看这个源码,待会呢老师给他底bug看,只要你这个next d内是小于零的,它就会进入到这段代码来做,如果不小于等于零,它干什么呢?它走这条这条线。那这条线大家看到就是这两个,它有什么本质的不同吗。大家有没有发现,如果听到这个if语句里面,他创建了一个idol state event这个事件。而这个事件正是reader idol。也就是他会创建一个读。Idol的事件读这个超,呃读读超时事件,读事件。读爱豆的事件。然后呢,在这里他会把这个事件抛出去。他会把这个事件抛出去,抛给谁呢?抛给你的那一个handler。
02:01
抛给你的哪个看到的就是抛给你这个ctx,把这个事件你扔给你。那这个CT是哪一个呢?就是你的那一个idol state handle的下一个那个要处理这个超时事件的那一个handler呢?Ctx,好,我这个说的有点绕啊,待会我马上就第bug,大家不要着急,那如果说没有,如果是大于零呢,他就不去。创建这个世界,好,大致的意思就明白了,那现在呢,老师给大家下一个断点。那我们在哪里下断点来进行测试呢?非常的简单,我们就在这下。来,朋友们,我们原先这个时间是五。是不是以前好像是五十十秒,现在呢?我想给大家演示读超时的时间,我把这个时间设置成十秒。把这两个,把后面两个时间呢,设置的稍微长一点,因为我我不想把它混在一起,明白我意思吧。
03:00
好,也就是说十秒过后就会产生一个什么事件呢?产生一个这样的东西,就是reader I读空弦的时间能理解好,那现在呢,我们把断点下在哪里,下在哪里,就下在这个位置。我们看看这个地方他会进来,他会怎么玩。我们追踪一下,大家就一目而了然了,好吧,一目而了然了,好,这是一个,我还想在这儿下个断点。就是你这个有个China idol,他会把这个读事件传给下一个,是不是传给下一个的话呢?诶各位朋友,那我在哪下一个呢?我在这下一个端点。就是因为我们知道一旦出现了这个呃事件,不管是reader idol还是writer ID还是allol,是不是就会触发我这一个handler的user event trigger,这个方法还记得吗?啊,其实你阅读源码也可以,你这下个断点看的更清晰一点,来,同学们,现在呢,老师要准备来玩一把了。首先我们。
04:05
第bug,我先把debug打开。看这有没有下断点啊好,我下两个断点,一个是这。一个是这明白好,现在呢,我们进行一个debug,运行起来认真听啊,同学们认真听。待会儿呢,老师给你们看一下这个代码,现在呢。呃,已经进入到一个active状态了,这个时候我们需要打开浏览器去连接一下,才会产生相应的事件,还记得吧?来,走起来。来走,我们现在去连接这个服务器,HTTP。Local host端口号是多少?还记得吗?端口号我记得好像是7000,没问题吧,同学们。好,来了。好,同学们看现在还没有动,没有动静。稍等。十秒过后才会到达我们这个位置来了。
05:00
是不是十秒到了,好,我们现在呢,往下追,此时此刻我们看这个代码往下走,同学看next底内是不是就是我们设置的。十秒钟没有问题吧,同学们,那么现在reading是一个什么值呢?Reading是一个false,那一旦是false,它就会去重新给我们计算这个next。好,那现在我们往下走,进到这面来了,它就用这种方式去计算,计算完了过后我们可以看到顶内next内呢,已经是个负数了。看是不是个负数,是负的多少多少一个纳秒值,显然它会进到这里面去产生一个reader I往下走来了,是不是他呃,他在产生的时候,是不是又把这个任务加入到一个schedule里面去了。是不是加到这里面去了,好继续往下走,走走进到这里面来了,那么进到这里面过后呢,他溜了一个idol state event。哎,大家还记不记得。我们以前讲过state,它其实就会对应我们这个server里面的某一个。
06:07
是不是大家还记不记不记不记得idol state event,它本身是一个什么呀?它是一个枚举,还有印象,不好回到这继续往下走。走好,继续往下走,你会看到他就走到哪儿了呢?走到这来了。看到没有,诶,他就走到这个下一个。My server handler的user event trigger的,没有,没问题吧,好,这个时候大家看传进来的这个event。这个疑问其实大家可以往里面看,就是一个reader I。那这个时候他显然就会干什么呢,就会进入到我们这个地方,然后往下走,是不是break到下面我们就输出了这个事件,那这边看控制台输出了一句话。这个控制台就应该输出了哪句话呢。
07:00
是不是?是不是输出这这这些话了,因为我在这停了好久呢,对不对,他就输出了好多次,看这边就说诶什么什么超时时间就到了。所以同学们,我们经过这个代码的阅读,大家是不是就把这个流程看得很清晰了,实际上就是在这里。呃,产生了一个。Reader爱豆事件,然后呢,把这个事件传给了我们下一个handler的。User event trigger的这个方法,然后你就做相应的处理。对相应的处理是什么处理呢?就你可以再发一个包,如果对方有响应,说明这个连接还是OK的,否则的话你就可以考虑关闭是不是好,这是老师的一个。啊,这是这是一个思路,好,接着我们再把刚才讲的东西再说一遍,触发的逻辑是首先将任务。啊,触发的逻辑是这样子的,来捋一捋。好的。如果读取结束了,呃,这样子小于零就触发事件,反之,继续放入队列。间隔时间是新的计算时间。刚才已经说过了,触发的逻辑是首先将任务再次放到我们队列,没问题吧?Schedule的方法时间是刚开始设置的时间,返回一个promise对象,用于取消操作。
08:19
那么。然后设置first属性为false,表示下次读取不再是第一次了。OK,因为刚才我们是第一次这个属性在channel read的方法被改成一个处。那么同时呢,这个地方是我们关键的产生一个I state event的一个事件。的一个事件哈,那如果是读,那就是读事件,写就是写事件,将此对象传递给用户的user trigger的方法完成出发。总的来说,每次读取操作都会记录一个时间,定时任务到了会计算当前时间和最后读的时间的间隔,如果间隔时间超过了设置时间,就触发这个时间。好,刚才已经说过了,那现在呢,我们再来看。
09:05
下面我们再看right I time out task,这里面方又怎么写的呢?其实这段代码就是这块。来,往下看。是不是就这个writer idol time task,他呢也继承了这一个类,所以说他这里面呢,也有自己的一套run方法。你们看到这个方法呢,跟前面几乎一样,只是多了一个这个,诶这个是干什么的呀,还是outputin这个方法,它主要是用来判断你的这个出站是不是有过于缓慢的数,过于缓慢的这个数据好。好,我们接着往下看,大家看写任务的,让代码逻辑基本和读逻辑一样,唯一不同就是有一个针对出站较慢数据的判断,越有可能呢。就是也有可能你呃,你认为出这这个超时了,有可能是因为出战速度慢造成的,所所以说呢,Nike的设计者也把这一个情况考虑进去了。
10:11
好,那现在呢,我给同学们来看看right事件能不能发生,同样我们在这下个断点。好,现在呢?我们找到serve。把时间修改一下,把这个时间改的长一点。把写超时的时间改成十秒。好,同学们,我把相关的断点处理一下。这个地方是哪里哈?Reader,好,我把这个段子就下掉了。这边是。呃,我们看看这边是哪里。540。嗯。
11:00
OK,这个怎么跑到这儿去了呢,重重重新下一下。这个点还是要保留的。我在这儿先下个底。下一个这个不不在这下。在right这下这下一个就可以了。就right吧。三个端点好的,那现在呢,我们基本上就找好了,关闭前一个debug的代码,现在呢,我们重新来run。来,走起来,同学们。首先。好,稍等,然后呢,我们仍然去请求一下。请求过等上十秒就会触发到我们这个writer idle timeout task。稍等。来了。好,同学们,可以看到现在呢,又出发的是right,而不是read read的这个I了啊,我们往下看,现在呢,Last right time时间它是记录下来了,这个时间就是按纳秒来计算的,OK,紧接着计算我们的这个next delay,这个时间算下来应该是多少呢?哎,它计算了啊,就是他把这个时间给你进行一个计算了,这系统时间减去last right time时间,然后再用这个时间去减。
12:13
对吧,就是你你这不是你设置的超时时间吗?减完了过后得到一个next内,如果这个时间小于零说明什么呀,说明有写超时发生,那现在呢往下走。说一旦业务这个事件发生,他先把这个任务加到我们这个schedule里面去了,就是加到这个队列里面去,往下继续走。继续走,显然这个地方呢,它调用一个方法去判断是不是是不是因为有这个出站,出站速度慢的问题,所以说接着往下走,到这来,到这来呢,它产生了一个。呃,Stay的idol state的event就是write idol往下走,下面走又到了我们这里,但是此时此刻传过来的事件呢?是什么时间,大家看一下。
13:01
这个时候这个事件就是我们的这个事件了,看一下。诶,把光标停在这儿。听到这也行。往下走,同学们看是不是这个是writer I,那如果是writer I呢,它就进到哪里去,进到这里面去。完成下面的代码没问题吧?好,这是我们所说的。Writer idol。Idol。Time or的task这个类,接着呢,我们来继续往下看,下一个就是all ile time task,但这个方法呢,呃,基本上和前面一样,但是你看他这也有,也有一个还是output前change景,但是他多了一个什么呢?他在判断这个新的这个时间的时候,他是这样来算的。他算的是这个。好,我们先来,先来把这个代码定在这个位置给大家看一下。往下走,下面呢,我们写到这个。
14:01
就是all idol time out。好,现在呢,我们把断点都下好了,同学们,我们先关闭本次第八个没问题吧,同学们现在呢,跑起来。第八个起来。现在诶,我我重新重新来一下第八个。Debug。用浏览器请求下。等待十秒,这次呢,他会到我们,诶,忘麻烦事了,不好意思。我没有改时间,没有改时间是看不到的。我把这个时间要调整一下。这个改成7000秒。这一个我们把其改成寺庙。啊,这样才可以的。来第八个。这次我们会进入到。新一个新的,呃,Time。
15:00
Time out啊。走起来。十秒。回到这个地方来,来了,大家可以看到它现在进入到all idle time out task啊,往下走。此时此刻我们可以看到原先这个时间哈是多少,是不是就是我们的十秒,然后这边肯定也是十秒了,然后呢,往下继续进去,重新计算一个next。那现在算下来过后是个什么字呢?显然这地方它应该是个负值,所以说小于零,小于零呢,它进到这里面去了。我要走。是不是把这个任务又进行了这样一个处理,叫schedule,接着继续往下走。挖走,同样去判断有没有出站数据过慢的问题。接着往下走。这时它产生的一个I state,就是all,再往下走,再往下走呢,又进入到user event trigger往下走到这里,这时我们的。
16:07
EVG,其实就是什么呢。就是all爱好,下面呢就会匹配到读写空闲,下一步读取。对,那这里呢,有一个地方我们需要稍微的给他说一下,就这。在哪里呢,就这。他在这里计算。下一次那个next内的时候呢,就next内的时候,他算的是last read time和last right last read time和last right time里面的最大值。为什么呢?因为它是读或写嘛,那显然它是求的一个最大值,这点大家清晰一下。好,我们接着往下看。所以说我在这写了,嗯这嗯就是。在这里我讲了这个时间哈,就是当前时间减去最后一次读或者写的时间,若大于零,表示超时。
17:00
嗯,还有这里的时间计算是取读写事件中最大的值,然后像然后像写事件一样继续判断啊,判断是否发生了写慢的情况,就是我们这有这个方法。就这个还是output体没问题。好,这是这里一个梳理,那最后呢,我们把ni的心跳机制做一个梳理。看一下。小结,Net心跳机制I state handler可以实现心跳功能,当服务器和客户端没有任何读写交互时,并超过了给定时间,则会触发handler的这个方法。是不是刚才我们也是追到这个方法了,用户可以该可以在该方法怎么去处理呢?尝试向对方发送一个消息,如果发送失败则关闭连接。就是因为你这个超时了,你超时了你可以怎么去处理,你可以尝试向对方发一个消息过去,看看对方有没有回应,如果发送失败,那这个就关闭了,可以。
18:06
Handle呢?他实。的实现。基于event loop的定时任务,每次读写都会记录一个值。在给定任务运行的时候呢,通过计算当前时间和设置时间。和设置时间和上市时间发生发生时间的结果来判断是否空闲。内部呢,有三个定时任务,分别对应读写读写。就是读事件,写事件,读写事件。通常一般我们去去监听读写时间就够了。就因因为你翻成读或者是写嘛,对不对,同时I state handle内部也考虑一些极端的情况。什么呢?就是客户端接收比较缓慢,一次接收数据速度超过了设置的空闲时间。那通过构造方法,有一个刚才大家看到的属性叫observe。
19:00
Output属性来决定是否对出站缓冲区的情况进行判断,就是你要你要不要判断,判断有这个出站慢的情况。如果出战缓慢,Nike呢?不认为这是空闲。也就不会触发空闲时间,但第一次无论无论如何是要触发的。就说比如说同学们看。我们定的是超时十秒,那第一次即使你是一个出战速度慢,那我也必须去触发一次,什么呢?这个空闲。为什么呢?因为第一次无法判断出站缓慢还是空闲,说他一定会触发一次,对还有一个情况就是如果出站缓慢的话呢,他有可能造成oom,就是这这样一个问题,OM比空闲是问题更大,所以说如果说同学们为了保险呢,你你就这样子,你就说如果速度慢的话呢,咱们就关闭也是可以的。第六点我们说一下。当你的应用出应用程序出现了内存溢出或者是OM之类的,并且写空闲极少发生。
20:08
比如说你在对方。把这个observe设使用了一个设置为处,那这个时候呢,就需要注意是不是数据出站速度慢造成的。对,还有一个地方需要同学们注意,就是read timeout read timeout handler,它会继承,他继承的是idle state handler,我们来看一下。也就是他是基于idol stay的这样过来的。那我们看它是基于I state handle,但是呢,我们要强调一点的是哪一个呢?就是right。Right right timeout handle,它不是基于idol stay handle。它的原理是什么呢?当调用write方法的时候,会创建一个定时任务,任务内容是根据传入的promise的完整情况来判断是否超出了写的时间,所以说两个机制不一样。
21:02
两个机制不一样,那么我们我们也来看right timeout,它是一个怎样的情况,来,朋友们。回到这里,大家看是不是它是直接就继承了China out bound handler adapter。对,所以说所以说老师我我我感觉在讲这个课的时候,这英文太长了,念起来非常的费劲啊,同学们你们可以一边听一边念一念,你们就知道。这个这个念起来很很麻烦,很很费劲。好,最后呢,他是干什么?当发现promise is done方法返回是个force时,表示还没有写完说明就超时了,因为我们知道promise呢,它是一个什么呀?Future,它是基于一个future的机制来处理的。因此呢,它可以通过is done来判断到底有没有超时,那如果超时了,就抛出一个异常对当right方法。完成后会打。呃,会干什么呢?
22:01
这个打断定时任务好。就是这样一个机制,好同学们,那关于我们这个心跳,就是hardbe的这个心跳的源码分析,我们就到这里,大家重点就是要搞清楚哪里呢?其实核心的地方就是要搞清楚我们的。I stay harder里面的这三个,一个是reader。A idol他们out,帕斯特,还有个这个,还有个这个。哦,还有呢,就是他们这其实是使用的一个wrong,这个wrong方法呢,是由他的负类提供的一个模板,下面呢,不同的处理方案,呃,不同的timeout,它是可能处理方式不太一样。好,各位同学,这里这一讲,我们就到这里。
我来说两句