00:00
各位,我们来分析一下绑定端口。服务器的就是在这个半的方法来启动和完成的,这是一个核心,那么我们来看这个半的方法。就下面这个方法。其实做了很多很多的工作,大家看这边写的很清楚,Star这个工,这个办的方法。做了太多太多事情,我们来简单的梳理梳理一下,首先这个band方法追进去的话呢,你会看到它这个地方调用了do band,我们注意一下。好,下面呢,肯定有实习。这个还得往里面追啊,要追下追到这了do b,也就说追到这个do band方法来了。好,那么通过这个办法band方法追踪,我们追到一个创建,它创建了一个端口对象,是不是创建一个端口对象,然后呢,做了一些空的判断,是不是你这个是不是空的,然后呢,核心代码是do band,我们追到这个do b里面去,我们看到这里面呢,又有两个核心的方法,一个叫it and register,一个叫do band0。
01:06
OK。豆瓣还是豆瓣的零,我看下。主办的零,这是这个是零号。那这里面分别是有进行初始化,还有一个注册,还有一个读,我们先来看哪一个呢?往下先把它大致的看一下,如果说这边追进去的话。就会知道这儿。这个方法实际上是实际上做了很多很多工作,而且呢,它返回了一个China future,我们讲过China future是一个异步执行的结果,对不对?好,我们来看看,首先那如果要分析的话呢,我们先要分析in it and register。然后再来分析,哪一个呢,还得去分析。最核心的do半零好这个这里面东西就非常的多了,那跟上老师思路往下走一下就可以了。我要走哈。我们先来分析一下it and register追到这里面去。
02:00
是这儿吧。追进去。好,其实这帮我已经下过断点了,大家有没有发现我们刚才说的China?真正创建China其实就在这个it and register,大家看到是不是这样子的,说白了就是你这个地方去初始化了我们的这个China,那接着往下看呢?看啊,大家看这里在这个方法里面呢,它调用了一个China factory.new China的方法作用的,这个作用通过。这个方法它是通过什么server bootstrap的通道工厂?反射创建一个n I server。好,这个刚才是不是大致的源码,我们也看过了。那这边做完了以后呢,下面会有一系列说法干什么呢?通过NIO的select provider。的这个方法得到JDK的channel,也就是他其实这个底层呢,他会先拿到JD channel,目的是让net包装JD channel,因为我们这个地方返回的channel呢,其实它也仍然来自于我们JDK的channel。
03:07
OK,第二个这个new China呢,它还创建了一个唯一的China ID。创建了一个n I message on shift,用于操作销售,还创建了一个default,这个很重要,Default China pipeline,哦,这个就很重要了,大家还记不记得我们整个是整个就是是有一个拍拍通道的。其实也是在这里进行一个创建,而且这个通道呢,是一个双向。链表的结构用于过滤所有的进出消息。还做了什么工作呢?创建那个n IO server China con对象,其实都在这里面做了。好,那有些同学我们看一下呢,如果你简单通过这个地方追可能是追不到的,因为他进去过后直接就是一个接口了,如果要追的话呢,咱们得按照这个代码一步一步往里面追。好,我们我们先把它先先说到这啊,因为他这个往里面追的事情就非常非常多了,我把这个说出来,大家应该大致也就知道了,如果往里面追的话,这个过程很复杂。
04:08
过程很复杂,那么我们接着先往下把整体认识了好,整体认识了再说吧。然后呢,我们再说一下这个nit。就是同学们这个I。Init初始化这个n IO server channel具体具体代码,最终代码过后呢,我们可以看到这样一些信息。就这个方法。这个方法做的也做了相当多的事情。前面我们说了,就是new呢,他做了以上一些事情,那么这个it方法又做了哪些事情呢?他把你得到的这个n IO server socket channel传递给这个I it方法做了哪些工作呢?看一下。这个方法呢,它是。在我们这个类里边。这个类由server boot来实现,可以注一下源码,那这个源码呢,是在这个位置啊,在这个位置,它的作用是设置NL server消相的TCP属性,由由于link的哈希map是非线程安全的,会使用同步进行处理。
05:13
那么n nio server China的chinapeline会添加我们的什么呢?China对象,这些都是经过的,可以看出ni方法的核心作用是在什么呢?和China pipeline进行关联。愁什么呢?从这个NL server的初始化过程中我们得知pipeline,它是一个双向链表,待会我们会注意这个东西的,不着急,并且它本身就初始化了hir和T。这里调用它的纳方法呢,就将整个hi,将整个hi插入到ter的前面,因为T啊TT永远会在后面做一些系统工作,也就是说我们将来形成这个链表呢,你会看到。它是这样的一个链表。比如说。
06:00
比如说这是一个T表,这是T,其实我们每加一个handler,并没有像我们想象的加到这个T的后面,而是加这个T的。这个位置的。他是这样子。明白吗?好,没不着急,待会呢,我给大家追一下这个源码就明白了,好,这个地方先简单的说到这啊,一会我们就追追源代码,好,我们来看基本说明IR初始化的这些信息,然后呢,Server通道反射创建了这么一个n IO server,刚才已经说了new。It初始化n nar China confi group register通过server BOO的boss group注册了一个这样的东西。最后。返回异步执行的站位及我们这个reg future。好,那现在呢,我们来证明一下,刚才这个端说的说法就是什么呀,它最终这一个拍on是个双向链表,我给大家追一下。
07:00
我们就找一个方法来追吧,我们追这个last好吗?我给大家看一下好不好,来走一个。要注意一下这个代码是可以给他看一下的。走一个。来,朋友们。在这儿放一下。OK。我们直接定位。怎么没进去啊?好不着急啊,同学们看。同学们看这里啊,他在这里做了什么工作呀?China pipeline是不是我们经常做的一个纳,是不是穿一个纳呀?好,那这个纳我们是怎么加距线呢?来看这里。是不是他整个这个过程最终啊,它掉的是这么一个方法。你看这同学们他做了哪些工作,这个方法其实应该好好研究一下的,他做了很多工作,当我们去添加一个handler的时候,Handler的时候。好,当然这里面它还可可以指定你加到哪一个组里边哈,可以还可以指定这个,那么我们一般情况下是调的这个参数,是不是我们调的是这种这种方式大家是不是我们知是纳写个名字在C,但这个方法呢,其实它默认会去调纳传一个空。
08:16
这个空间代表我是在我当前的这一个China进行添加一个名字handleer,还是调到这来了,调这来过后呢,大家有没有发现它其实是在添加hander的时候先创建一个context。然后呢,把这个contact加到了我们这个链表的最后,那也就是说真正往里面添加是I纳零在哪里呢,在这。来,我们分析一下这段代码,各位朋友。你看他是怎么做的啊,比如说我们这已然有个双向链表了。来简单分析一下。现在呢,这个时候是个T。各位朋友看一下这个T呢,它你现在产生了新的handler context,这个handler contact里面肯定有个handler。
09:04
这是不用说的。好,那这里呢,他先把这个TP。放到了这个,就就相当于这个pre指向了T的前面一个,也就目前呢,我们可以认为P这个指针。指向了它,然后呢,大家看我们新的新的这个handle怎么加进去的,好,这个是假设是我们的六。它的这个6P先指向pre,那就是让它先指向它咯。没问题吧,然后呢,让t.next指向T,那就是让它指向咯。能理解吗?然后这句话是什么?点next等于new。这个你新的这个,那就是这个。这个pre没有不在这来了,这个pre呢,指向了他。好,再来t.pray。指向了你就他点指向他了。
10:03
看到没有?是不是,那我们我们看一下现在是不是这样一个情况呢?诶这边还有一个new。啊,这个地方是不是忘写了呀,妞。New next下一个指向它,那new play呢啊new p指向这个指向它了,所以说你看这个指向了它前面指向它,它后面这个往后指的指针指向了它。对不对,这样就关联起来了。再去管理起来。好,所以说这样子呢,就相当于把我们这一个新的,就是新的这个context插入到T的前面。仍然形成一个双向链表。没问题吧,我看这个线。呃,这这根线呢,这根线好像没动过呀,我看这根线应该指向它才对呀,我们再来分析一下。A t period next。这个动作看刚才这句话说错了啊,大家看我刚才有个地方没有分析对,没有分析对,是说有点问题,我刚才这个分析是不对的,他这有个pre next next pre next指向新的,而不是pre指向新的,那相当于说这这还有一条线。
11:16
这才对的呢。是不是刚才我分析有问题啊,我我认为是pre指向的new contact,而不是的,你要是PRe.next指向new contact,那这样子就这样一个线。对不对。这样就行,当然这这中间这两条线自然就断掉了。明白哈,因为最后我们最后这个太阳呢,总是放在最后的,他是刚才正如我们这个文档里面所说的一样。文档里面所说的一样,看我这儿不是写了这样一句话吗?对。看到。呃,拍on,那是一个双向链表,并且它本身就初始化了,Hi和这个T就是hide和太阳呢,实际上是初始化过程中就已经有的,这个是不能去动的,这里调用了纳呢,它就将整个handle插入到T的前面,因为它要永远在后面,需要做一些系统的固定工作。
12:10
所以说刚才老师画的那个图就是在说这个事情。从研发的角度做了一个说明。好的。好,这块我们就说清楚了,说清楚过后呢,下面这这个我就不再去念了,好,就是last,它在什么什么方法内中做了什么事情呢?这个方法是拍line的核心,它检查handler是否符合标准,创建一个这样的handler contact对象,这里说一下handler China China handleler contact对象呢是。它是controller China handleler和China pepeline之间的一个关联。对吧,每当有一个China添加到pipe的时候呢,都会创建一个contact。所以说我们这一个contact,实际上呢,它在添加handle的时候创建的contact,主要功能就是管理它关内的handleer和同一个pipeline中其他的handler相互交互之间进行交互。
13:08
将context添加到链表,其实就是叫T节点的前面,就是刚才老师画的一个东西,最后还有一个动作,同步或异步啊,同步或者异步,或者晚点异步的调用我们的call handler。Added。这个方法其实就是在最后这帮是大家可以看到的,就它。没问题。紧接着我们。这个说完了,下面呢,我们再看最后一个读办的方法。呢,这里面最为核心就这个方法又又得回到哪里呢?又得回到我们最前面去。这个读办的方法有两个重要的步骤,一个就是刚才已经说完的in it and register,现在呢,我们看这个督办的零,这个读办的零呢,其实大家有发现它会去调用China band。
14:00
这个China呢,他最近会把我们的local address放进去,这地方我们可以下个断点。就会放到这里面来调用China绑,因为你现在这个China已经创建成功了,所以说通过这个China来绑绑定,绑定过后呢,下面接着往下看。如果我们一直下断点,最后第bug呢,会debug的到这个unsafe办。这个on慢呢,继续往下追,我们会知道一个do办这个方法,这个方法同学们就是一个。真正的调用的,因为到这里呢,其实已经到哪里去了,已经到我们这个n IO server了。好,我们可以把断点呢,给同学们下到这里来,我们看是不是会执行到这个方法,那我这儿就这样子啊,咱们这就简单一点,直接在这下个断点就行了。多半。我在这给咱们给各位同学下个断点。最后。最后呢,这个do do办的方法在这里,好,我们。
15:02
在这下个端点。豆瓣,豆瓣的最终是在哪呢?是在这儿啊,在这儿也可以。我给同学们下个断点,我们来追一下会发生什么事情。好的,郭同学大概是在这个位置,我记得。正因为方法很多哈,我们要找到对应的这个方法。不是这儿。我在这儿搜一下。搜一下啊,那就从这找吧。因为那边的方法还是很多的,咱们一时半会找不到它的源码。好,在这儿就找到了下一个。好,我在这儿呢。同学们看一下我在这下个断点,最终它会执行到哪里呢?执行到Java china.band。对,Java China版等等,其实到这里面已经是IO server so China这个东西了。
16:01
对吧,因为我们知道ni呢,它是对NIO的一个包装,所以说我把断底下到这呢,我们就可以一步一步往下执行,那同学们我们来准备执行一把。看看能不能到这儿。好。Debug。Debug下。那下面我放过这个断点再放过。再放过一次那点。再放过。好同学们看我们到这里来了,那到这里了呢,其实已经把你的这一个noho拿到对吧,端是8007,那现在呢,我们往这里面执行它就可以。看的更多,看到没有。它调用的是server,它父类的Java channel继续可以往里面追。返回了一个selectable channel。返回。然后呢,我们可以继续。这个地方可以继续再返回。
17:02
是不是又到这来了,到这来过后呢,这个地方其实刚才执行的是configuring get backlog,然后继续往里面追。又返回一个。对不对,又回来,然后再往里面追。这个时候呢,其实这个band就到下一行,那下一行如果我们一直往下追,会得到一个什么效果呢?最后如果一直往下追,我们就会追到这个run方法,所以说我在这门文档里面呢,给大家看到,如果我们在这个B地方一直用往下执行的时候呢,最后会执行到safe。呃,Set success,如果执行到这个地方呢,就告诉promise任务完成了。七七可以执行,就是说它可以执行监听器的方法了,到此整个启动就结束,启动这个结束过后呢,如果我们继续往下走,就会执行到哪呢?N IO event loop的一个循环代码,因为我们最终大家知道服务器它是要进行这个时间循环的。
18:02
大家回忆到我们最先前讲的这个东西,大家还记不记得?在我们最先前讲的时候啊,这个地方有点有点不好找了,我就不去找他了,就是大家还记不记得我们在实验讲的时候,最终是要在n IO event loop进行这个循环进行监听,那么我们可以在这再来追一下。好,下面呢,我把这个不要的断点先给他拿掉,就保留一个断点,我给大家追一下就可以。好,我保留这一个端点哈。保留哪一个断点呢?保留。这个端点就行。好的,同学们,我们来把它停掉。然后呢,再来第八个一把,我们看这个时候能不能进到那一个run函数里面去进行监听。好的,那现在老师一步步走了,走走走好。接着继续走。走。走,你看。这个地方是不是执行到safe set access。
19:02
这个地方一旦执行完了,就说明我们这个刚才老师所说的这个时候呢,就已经把什么事情做完了,就说这个这个任务已经执行完毕了,气可以执行监听器的方法了,那接接着继续往下走。挖糟糟。看到没有返回绑定,再返回走下一步又返回跳一系列的pipeline操作。好,往下走,同学们看这里。关键地方来了,大家看它现在进入到一个什么呢?负循环。对,复习完接着往下走。往走看这边又是不是又到这边来了。走走走走走走走走走走。走。走。走,诶看。是不是到这来了?同学们,我们经过一系列的追踪,终于到这儿了。而这面run呢,它就会根据你。
20:02
相关的事件进行处理。看到没有,他这边会拿你的事事情,那相关的事件进行处理,那这个时候呢,他就会在我们这个事件里面跑了。走。对,来看处理,看是不是这个东西了process,诶,我现在就给你们看一下这个方法了,大家还记不记得我们在前面讲。我们讲这一个就是ninety模型的时候,大家是不是还有个印象啊。我们是不是说在整个循环过程中,往下前面看一下不着急啊同学们。我给你们看到这个方法。来吧各位,是不是我们说在boss group还是worker,它的event lo里面会有三个步骤,第一个是select。然后呢,再process select selected k,然后再run我们的这个all task是不是这样三步来看看是不是这样子的同学们。
21:07
给大家是不是现在已经到这一步执行过去了,好接着往下走。是不是,Run all tasks,是不是,然后又干什么又干什么走。接着走,是不是又到这边又进行一个操作了。然后又干什么,是不是这select?是不是接着再走?是不是又又到这边来,然后呢,继续往下走,是不是又来开始处理我们相关事件,是现在他没拿到,所以他没没有相关的K,他就跳过去了,然后这边又来执行我们的什么呀,让我们的all task1推,所以说其实到这个地方我们就已经追到哪里呢?追到这块了。追到同学们,同学们想看到这个位置就哪一块呢,这。是不是已经结束了呀,如果说他这个地方,如果执行到了这一个,同学们,如果他有关心的事件,如果你真的有件事情发生了,他就马上到这里面去调用它相关的pipeline,相应的去处理,当然这个整个过程中呢,又会通过我们handle德尔练,原先讲的handle德尔练的机制进行入战和出战操作好同学们那关于。
22:21
我我想啊,关于我们这一个let启动过程源码,我们就分析到这里。最终呢,我们是追到了他的哪一块呢?就是同学们看到的这块。当然了,我还是那句话,就是大家可能还是觉得,嗯,就是追的,可能还是觉得,诶听着有点乱呼呼的,我跟大家讲,如果你自己去自己去追,你会追的更乱,因为他这个ni啊,它包装了n IO nio呢,又包装了Java,他包了很多层。如果我们按照这个。而且又又基于是网络多线程的,所以说他用这个debug本身就有点难,所以这个时候呢,只能我们这样子去跑一篇了,好吧,大家呢,就如果哪块没有听明白,我把这个文档到时候会分享给大家,我会放到这个笔记里面去的,就是到时间我会这样做,把整个这个笔记也分享给大家,同学们呢,可以按照这个流程自己再走一圈。
23:13
就会对它认识的更加清晰。好,同学们那关于net启动过程的一个剖析,我们就聊到这里。
我来说两句