00:01
心跳。也就是我们前面讲的heartbeat服务源码剖析。我们来看一下源码剖析的目的,Nit作为一个网络框架,提供了很多的功能,比如说咱们的编码、解码,Nit还提供了非常重要的一个服务,就是心跳机制。同学们还记不记得我们在前面呢,已经举了一个heartbeat案例。那Nike通过心跳检测对方是否有效,就是?相当于说你的客户端和服务器,服务器端他们这个连接是否还有效。这是RPC框架中不可缺少的功能,那下面呢,我们就来分析一下nit内部心跳服务源码。首先我们对他做一个基本的说明。Ninety,其实这里他一共提供了像idol state handle,还有read timeout handler,还有一个time right。Come out handler,这三个handler检测连接的有效性,那这里呢,我们重点给同学们分析一下I state handler,为什么呢?待会我们说明,因为。
01:11
大家看我这里先做一个简单介介绍啊。Read timeout handler和write timeout handler它是什么意思呢?他这样子的,如果在指定的时间是时间指定的事件。没有。指定的时间吧,这个应该是写错了啊,指定的时间没有发生读事件就会抛出异常,并且呢会自动关闭这个连接,所以说我们可以在exception catch这个方法中处理这个异常。对于rightout time right timeout handler呢?当一个写操作不能在一定时间内完成时,也会抛出一个异常。并关闭连接,我们同样也可以在exception catch方法中处理这个异常,所以说关于这两个异常呢,它本身就发生的时候,他就直接。
02:05
把这个连接给关闭了,因此呢,我们重点就来分析I state handler它的处理机制。那同学们,那现在呢,我们就来看整个源码分析的过程。打开。我们来看一下如何分析。前面呢,我已然介绍了来提供的这三个handler对不对?那现在呢,我们看刚才老师所说的read timeout事件和write timeout事件会自动关闭连接,而且属于异常处理,所以我们这里呢,重点看I stay handler。那现在我们来看一下I state handle的源码。打开这里。还。IDE。别老idol。State。
03:00
State。Handle。没问题吧?好,我们来看一下,那现在呢,我们看它的整体的一个结构,同学们看。I state handle呢,实际实际上它的内容非常的多。我们首先来看它一些核心的属性,哪些属性来lawyer。它提供了有这么四个属性。那我们打,我们在源码里面先把它找到。在这看。是不是这四个。看到没有?Private final booing observe output,还有一个read idol time。他们nano这个是纳秒的意思,大家知道什么是纳秒吧。就他这个统计时间呢,超时或者是呃,说也说他超时的时间单位呢,是纳秒纳秒纳秒大家知道是。什么样一个单位吗?是十亿分之一秒,就是纳秒。这个是writer。
04:00
Idol他nano,还有这个是哦,Idol他nano,那这个地方。解释一下它的意思,第一个呢,Op observe up是否考虑出站慢的情况,默认是bos,嗯,那这里我先简单的解释一下,为什么在处理超时的时候还要考虑出站慢。的问题呢,大家想,比如说我这里是一个。客户端这边是个server端。同学们。比如说我在这里发送一个数据过去。对吧,好,第一次呢,我发送的时间,发送的时间是五五秒就完成了,对不对,那我设置的。你来了,我是不是就读这个事情呢,所以说我读超时呢,假如是十秒。你五秒就发过来,那么我就没有发生读超时的问题,但是大家也知道我们数据在网络上传输。这个连接可能仍然是有效的。
05:00
但是这是因为网络出战。速度,呃,速度慢,或者网络传输速度慢,他这次是20秒才发过来,那你的超时时间本身十秒他就超时了,实际上这个连接还是有效的,为什么呢?只是他慢而已。因此na的设计者呢,他在这个iol state handle里面设了一个属性,叫做observe output,就是是否考虑出战慢的情况。那么最终它在这个地方会有一个函数来体现。哎,它有一个函数的体现,待会我们往下分析,还有一个read I time,那是读写空闲时间,零表示静止,如果我是个零,就代表我不去检测,那接着往下看下一个right at time。那是表示写事件的空闲时间。下面all I time,那是代表读或写的空闲时间。大家看读或者写哈,那这个地方它算的时候应该是算算它的一个最大值,最大的一个时间,接着我们先来看。
06:05
Handler艾迪的这个方法,这个方法我在前面已经讲过了,就是当handler被添加到pipeline的时候。的时候,他就会调用这个initial。Initial在这个里面呢,它有相关的这些方法。哎,看到没有,就说这个idol。这个这个handler I是handler被天骄PA哦。呃,在这个。在这个handle ID的这个方法里面呢,它会去调用一个initialize方法,我们来看一下,这个方法是我们一个比较,呃,应该说是比较核心的一个方法来看一下。好,我们打开。我们就就在这直接找吧。对,不跟上我的思路。在这头我们诶定位找到initial。
07:05
看到没有?诶,同学们看到它传进来一个China hundred contact,就是我们所说的ctx,在这里面呢,他做了一系列的操作,我们来看看这个操作是在做一个怎样的事情哈,做一个怎样的事情。呃,这个地方我先说他这里面有个方法,就是这个方法,大家知道是干什么吗。Not time。好,我给大家演示一下,我在这写一个写一个文件,先先说一下这个方法,是因为这里面好多地方都用到这个方法了。大家看这个,呃,Tricks那呃tricks in number,你往这里面去看,它其实是调的就是system long time,这个是返回当前的时间,而且是按什么呢?按这个纳秒来返回的,我给大家简单演示一下。好,我在这写一个。Test方法。
08:01
啊,Test的类,然后呢,在这里我们。来测试一下该方法到底是个啥意思。呃,这样子system。System。运行我先给各位朋友运行一下。同学们可以看到现在它返回的是个什么呢?返回的就是。一个纳秒,按纳秒来计算的。那首先我们说那叫。那秒。纳秒是10亿,就是一秒的,就说十亿分之一。就这样写。10亿。十亿分之一,10亿。分支。1%。好,所以说这个就地方返回的就是一个纳秒时间,那怎么来验证验证呢?同学们看,我在这里休眠一秒钟,大家可以看到他们一秒,他们相差的就是1/11的样子。
09:10
我先休眠一秒。然后呢,我在。打印出当前的纳秒时间。这里我们扔出一个异常。朋友们,我们再来分析。大家看我在打第一个时间的时候呢,休眠了一秒过后再打第二个时间,大家看这里面,大家看这个时间和这个时间是不是差不多,相差10亿。是不是相差11啊,我们来看一下。我们用这个。运上去来减掉。减掉下面上面这个时间。差不多是相差多大呢?相差11。同学们看是不是相差11?个十百千万十万百万千万亿十亿,当然他还是有一有一点,这这个时间不不完全是个10亿啊,为什么?因为你你这个10亿分之,它这个时间单位已经非常的微小了,所以说会有一些出入,这是呃有可能的,因为你休眠的时候,你本本身调这个函数还是需要时间吗。
10:18
对不对,如果你把这些时间的调用,呃,函数的调用时间也去掉的话,应该是1/11,你看这个时间是非常接近11了。所以说我们要明白这个system.nano time,它的作用是什么,好,回到这边继续来看。回到这边,我们继续来看,往下走。回到刚才我们所说的initial这个方法,继续往下玩。那么现在呢?我们对这个代码来进行一个简单的阅读。来,请阅读。同学们看这里。看这里啊,同学们注意听。如果这个reader I time,那么要大于零说明什么呀?就说这里的schedule方法,会调用路的schedule方法,将定时任务添加到对里中。
11:03
是不是一个定时任务的schedule,如果这个right I time number na大于零,那么他就会去也做相应的一个调度,如果是all I time numbers大于零,他也会把这个任务放到这个里面去,那他在做什么事情呢?大家看我这里已经做了一个说明,只要给定的参数大于零,就创建一个定时任务,每个事件都会创建就是。嗯,就是如果你写超时了,那么我就创建写的定时任务,读超时了就创建读的超时任务。还有一点呢,它在这里面有一个动作,将state状态置为一,防止重复初始化,看到没有,那这面有个initial output change,这个方法是初始什么呢?监控出站数据的属性。好,这个基本的一个东西说完了之后我们来看。该类。就是我们这个idol类里面三个定时任务类非常的重要,这三个定时任务类呢,都是类不类,一个是read idol time time out task,一个是right,一个是all idle time,好,我们来看一下。
12:13
那现在呢,我们。来找到找到这三个核心的类,大家看这是不是一个累不累啊。他继承了abstract。I task,而这个呢,大家看这个right。是不是也继承了这个类,还有同学们看到的哦,是不是也继承这个类了,那现在呢,我们来看它到底是怎么玩的。怎么玩这个事情的呢?同学们看这个abstract。I帕克,其实它相当于是提供了一个模板。他提供了一个模板,我在这个地方呢,也有说明,来看看这里,这三个历史任务分别对应的是读写读或者写事件,他们有一个共同的分类,就它该分类提供了一个模板方法,就是同学们看到的这个东西,Run。
13:07
他这是干什么?干件什么事情呢?看这个源代码,大家能读出来在做什么事情吗?在做什么事情?大家看出来在做什么事情没有没有,也就是说从我们这个模板它可以看出来,当通道关闭了,就不执行任务了,就是你看这个Ctx.channel这个不就是把它的通道拿到吗?Is open,如果整个这个返回是一个什么呀?如果是返回一个false,那么就return了就结束,否则怎么办?Wrong wrong这个方法是不是你这自己要写的呀。那么至于你这个run方法,你怎么写,是取决于你的子类。也就是说,这几个类。根据你的逻辑来写,你是读超时,你就按读超时去处理,写就按写哦,爱豆就按说读或者写超时时间来来处理,所以他这里呢,用了一个模板设计模式。
14:07
好的,那既然如此,我们现在呢,就来开始详细的分析这三个,那么我们待会儿呢,用代码进行第八个。
我来说两句