00:00
Netty核心源码抛弃。先对他做基本说明。只有看过Nike的源码,我们才能说真正的掌握了Nike框架。至少你要把Nike它最核心的源码进行阅读。把我们ni的一些核心的机制,从源码的这个角度来进行理解。那么在net这个框架里边呢,它本身有一个包,就是ne io.net.exam点。这个echo这个包下面呢,它有很多的源码案例,我们来看一下。大家可以看到,在我们下载的Nike相关的源码包这。大家看这里面有一个exam。对不对?那么io.net exam这个包下面有很多的源码案例,我们可以用来做分析,那这里我先给大家说一下,我们本章讲解的源码剖析呢,是针对有Java项目经验的学员而言,并且呢,最好自己看过相关的。
01:08
框架源码,比如说你看过SP。或者是spring mvc,或者是tru two等等这样的源码的同学呢,听起来会比较轻松,如果同学们在这块没有做过任何源码剖析,听起来会有一点难度啊,但是当然你也可以听哈,就听起来你会感觉到呢,好像就是有点。有点不太好理解,那我先把这一点给他说清楚,那现在呢,我们来看一下,我们先对net启动过程进行源码剖析。我们怎么做呢?我们用源码的方式走一下ni启动过程,当然这里主要指的是服务器。更好的理解Nike整体的设计和运行的机制,好的,我们来看一下说明。我们整整个这个nit启动过程源码剖析呢,需要剖析到ni调用do band这个方法,因为这里呢,它就会开始进行我们程序的监听了。
02:09
而且要到追踪到哪里呢?追追踪到IO serveret China。这个demand的大家都知道,我们ni呢,它是在NIO的基础上进行一个包装的,是不是。也就是说我们ni的它的一个监听,最终呢,它还是调的n IO server channel。他这个这个NL server里面也有,最终要最终我们要追到这里来。第二个呢,我们要debug程序到IO loop这个类里面,它有一段wrong代码。大家知道no event loop,它是一个事件循环。他在这面循环干什么呢?在服务器端循环进行事件的一个监听和选择,大家都知道我们这个n IO event loop呢,它其实是有一个select的,就是选择器,这个选择器其实它属于监听的状态,它会根据你的这个情况来选择相应的事件啊,得到他关心的事件,再选择相关的通道进行进行相关相应的操作。
03:16
是吧,所以说我们打开这个源码剖析,那么源码剖析呢,它相对。原先我们讲的内容呢,比较的杂,因为我们这边是针对多线程进行源码剖析,所以说我这呢已经有些准备了,来看一下。我们这边有些相关的。源码剖析的文档,我已经把它整理好了,也花了很多时间来整理,我们就按照老师整理的这个文档,咱们一步一步往下看。然后呢,需要对源码剖析的时候呢,我们就给大家debug一下往下走。首先呢,我们先对这个DEMO文件,就是源码进行一个基本的理解,那首先我在这里先把它的。
04:01
先在这建一个包吧,我们先nit,下边我们建一个source源码包,So。OK,那现在呢,我从。他的元宝包这边拿一些案例过来使用,在exam下边有一个echo,我就拿这个echo好吧。往这儿粘。复制过来。那么我们先来看一下它的源码的这个案例是做一个什么说明,同学们可以看到。案例很简单。就是服务器这端,我们来看一下服务器这端呢,他先对它做了一个SSL的配置。就是SS配置就是configure s SL。然后呢,这边做了服务器的配置,然后监听了一个端口,监听端口。对。8007监听的是这个端口。客户端这边做了什么事情呢?客户端这边事情也很简单,他就连接。
05:01
连接我在这里,他去connect。连接到我们的这个服务器,然后呢。在这边有写了一个handler,这个handler里面做了做的事情也是非常简单的,大家可以看到。他在这里做了一件什么事情,看一下,就是在这有个read,这个read方法呢,他把接收到的消息输出来了。就这一件事情。那现在呢,我们重点是在分析。这个server就server阶段,它到底是怎么启动起来,最后。到监听。客户端发连接,或者说监听客户端的这个连接行为,那我们来追一下。那打开这个文档,我们一部一部分,首先大家看到是服务器启动,启动类的源码,就是同学们刚才看到的这个文件。哪个文件呢?Server,好,我们先重点分析哪一块呢?重点分析这两句话。
06:00
好,就是loop group。还有这个地方有一个boss group,这两句话到底发生什么事情,先把这个分析一下,往下走。好,先看启动类,命令方法中首先配置了关于SSL的配置类,就是这个。这块不是我们分析的重点,所以说我就跳过。接着继续往下看。重点分析创建的event loop2个对象,这两个代码接着看,这两个对象呢?是ni的核心对象,可以说整个Nike的运作都依赖于他们。Boss group用于接收TCP请求,他会将请求转交给worker group worker group呢会获取到真正的连接,然后和连接进行通讯。比如。读写、解码、编码等操作。关于这一点,是不是在前面写代码的时候,大家应该都有说,都有一些这个这个直接的接触了,那现在呢,我们来看event event group group,它是事件循环组,其实它是一个线程组,还有多个event lo可以注册China。
07:14
用于在事件循环过程中去进行选择,选择的时候呢是由选择器相关的,我们可以来debug一下。我们可以来debug一下,在哪去debug呢?好,我们把断点呢先下载到这里。没问题吧?我直接在这里debug一下。各位看一下。往下看。好的,同学们看,现在我把光标移动到worker group的时候呢?这边有个boss group。Boss group,因为这边还没创建起来,对不对,所以说我们往下执行一步,执行一步呢,我们把公标移动到worker group,首先看worker group,它其实是IO event group,它下边呢。
08:07
还有很多的child,也就是子线程,那子线程里面有八个,每一个呢都是IO event loop,就是我这说的这个东西。也就是说,Lo group是个事件循环组,它下面包含很多这个世界循环。对的,那接着继续往下走吧。第三句。我们六一个IO event group group,这个一表示boss group事件中只有一个线程,你可以指定,如果在我们创建的时候没有指定这个参数,默认会有CPU的核数乘以二这么多个线程,那么它实际目的主要是利用使用多。它可充分利用多核的优势,我们来给大家简单debug一下。好,我先停止debug,我们重新来debug,我们往这里面追一下,看看它是怎么一步一步走到能够去创建指定个数的线程的,我就追进去。
09:05
好,最近首先呢,大家看到他先付了一个零给你,对不对,他先到了IO group。这一个无参的构造器,然后在这里面他补了一个零追进去。到这来,到这来过,当然此时此刻n stress这个就是零了,大家把把光标写在这零,接着继续往下走。进去追进去。好的,又到这儿来了,接着继续追。追。追。好,继续追。记住大家看这边一系列参数都有哈,再看N还是等于零,这个S就是执行器呢,那是空,待会我们再说,执行器的事继续。好,同学们,看到这边大家有没有看到N已经变成八了。这个传过是八,那为什么是八呢?为什么是八呢?同学们还注意注,有没有注意到刚才我们在调用这个的时候。
10:05
这个地方。我们这儿再给他追一下。在这走。大家看这个字。这个default event loop stress,它是怎么得到的呢?它其实是在静态代码块进行一个初始化,是不是前面我们已经说过了,你看这里。就说他在这里面求一个最大值。要么是一,要么就是这个字。这个值是怎么拿到的呢?同学们看是native runtime.a a available processs,这个方法就能得到我们当前计算机的有效的合数,当然我这个机器是四核,所四乘以二就等于八,于是乎这边呢,同学们看到的。嘿,你跑哪儿去了?这连上哪去了,我看一下。现在呢,应该是在这儿。
11:00
好,应该是在这,也就是现在为什么你看到NS是八就这么来的,就这么来的,好,回头我们继续往下分析。往下分析这个就没什么,没什么说的,那现在呢,我们来看,在这段代码里面呢,我们一直往往下面追,会追到这样一句话。叫做差的等于六。Event a executor就是它的一个执行器,那换言之,我们这些child都是同学们看到的,它的直线层实际上是放在一个。叫做new。呃,叫做event executor这一个数组里面的里面有八个,那么我们也来第八个一下,看看它是在哪里。生成的好吧,那下面我们继续继续往下追,那这个我先停一下。停下呢,我们这一次把断点下在这个位置。下在哪个位置呢?我们这儿可以简单追一下。走。我快速的。走走。
12:02
好到super。再到super。再到,This,好,同学们到这里来了。大家看到他最终会执行哪一个方法呢?执行这个。这个方法。对,那这个这个里面有一个什么呢?大家看看到这里面有一个child等于new event exor,这个呢,这个时候这个等于八,那这个圈的类型到底是什么类型呢?我们下个断点来进行一个阅读。也就是说,你创建的这些一系列的事件循环实际上是在这里。这里先创建了一个数组,然后通过这个for循环来创建的,大家看这里真正创建是在new char里面创建的,而且大家有没有发现他在创建一个new的时候,同时给它放入了什么一个执行器?那也就是说整个你的这一个子线程,其实是靠这个执行器来帮你去执行的,那这个执行器是怎么创建起来的呢?待会儿我们再说好吧,好,我现在把断点下到这里,我们继继续来debug一下。
13:06
跟着老师思路好,同学们。好的,断点已经到这里来了,我们往下执行一步,此时此刻,NS现在等于八。哦,这这个为为什么是这里啊,是因为它这个地方我们代码是先从这儿进去的。对不对,因为先是boss group,我这指定的一。啊,如果说同学们想看到八的话呢,可以让这个断,把这个断点放过去,直接到下个断点就可以了。好,这个时候又来了,到这来了吧,我在下一个断点,到这来了,好再执行,这个时候N数就应该等于八了。是不是等于八了,因为我我放过了刚才的一个端点,好,我们来看这个child,它真实的类型呢,可以看是event,看到没有它是eventor。啊,这个时候它是这个类型啊,但是它创建完了过后,这个类型就有可能发生变化,来看一下,其实它真实的里面的每个元素,就是它每个元素类型到底是什么呢?我们让它创建一个往下走走走,好同学们可以看到。
14:09
此时此刻,这个执行器。就这个跟这个线程关联的执行器,实际上是叫。Per task明白。明白,好,那现在呢,它其实这个执行器是依赖于一个default factor帮你创建起来的。那现在呢,我们来看它真实类型是什么,大家看。哦,OK,往下点。现在第一个第零个已经创建起来,就是n IO event路就这来了,而而且同学们有兴趣的话呢,你可以追我们这个执行器啊,其实他们后面都。都有一个就是这个执行,为什么我们可以把这个NIO,就是我们把n IO event。Loop这种类型放在event ex呢,因为他们最终都有一个共同的副接口,我们来看是不是这样子的。
15:04
来,走一个。我给同学们看下。同学们看这个event event executor往下看。大家看接着往下走是不是event lo的往上走的负接口,就是event hor,再往下面走一个,大家有没有发现再往下面走里面有一个叫IO event loop这个实现内,它其实呢,是single thread event loop的什么呀子类,而它呢,又实现了event loop这个接口,而这个接口又往上走,又继承了这个接口,这个接口又继承了这个接口,因此我们把一个NIO里面的loop这样的实例。放到这个接口的速度里面是没有问题的。OK,好,就是这么一回事啊,那当然你整个这个for循环,大家有没有发现他其实还干了很多很多的事情,大家看他是怎么做的呀。
16:00
你看它每每循环一次。我们直接按照看就行了,大家看下面我就不讲了啊,不讲那么看到每个元素是什么什么类型不说了。呃,OK。嗯,这里面是不是还加了一些监听器。好。这地方是。这说的,如果我们发生了一个异常,他会把当前这一个。他会把你这个线程进行一个关闭,看到没有OK,同时呢,他会把你这一个当这个相关的相关的这一个什么呀,Executor也进行一个处理。看到没有,把这个E也进行一个处理。那接着继续往下,往下走,继续往下走,大家有没有发现他还做了一件事情。做了些什么事情呢?就是给我们每一个这一个就是这个E看到没有,他从这个child里面,就是这个child,不是我们当得到的这个event。
17:02
呃,就是这个child呢,具体的child肯定这个了,N IO event loop对他做了监听,看到没有还加监听器了,这块大家要明白。好,我们接着继续往下看,在TRY这个块里面呢,它还创建了一个server boot strip对象,它是一个引导类,它用于启动服务器和引导整个程序的初始化。我们呢?来往下看一下,他是做一件什么事情啊,他是做了一件什么事情。它本身呢,是跟这个server China关联的,而server呢,它实际上是继承了,所以说它有相关的一些方法可以供我们使用,我们来在这下个断点。还是在这下一段点,我们看一下它到底是什么类型哈,来走一个。来,我在这儿呢,下一个断点。早起来运气。好,我直接放过这个断点。
18:01
再放一次,断点到这来了,往下直起。好,我们可以看到这个B,这个B这个类型已经是server bootrip是吧,它下面呢,其实包含了很多很多的信息。对不对,包含了很多信息,那么我们继续继续往下看,他做了哪些事情呢?对,首先它是a no easy boorip of serve,它其实是用来干什么,启动,启动我们的一个server的。而且呢,大家看到它和server channel是关联起来的,为什么呢?大家往下看。接着往下看啊。呃,往往下走。随后这一个B调用了group方法,将两个group放入自己的字段。这个呢,我们继续往下执行,现在还没有走这个段代码走。好,同学们看这里。我们进到group进去看。同学们有没有发现在这里呢?
19:00
他也把我们boss group叫做parent group。把这一个worker group叫做char group,所以说在有些代码编程的时候呢,他把这个boss group取名叫parent group,把group取名叫char group也是可以的。对,大家看到这这个问题没有,他把这个parent group放入了,调用他的父类把它放进去了,最后我们这个char group其实是跟他的一个char group关联起来的,这个在哪里呢?就这个在哪里呢?同学们要同学们可以看。同学们,我们我们可以在这下,我们在这直接看一下它什么类型,大家看到没有,这个是个char group,它是event group group。是不是所以说通这个方式呢,就把两个事情已经做完了,一个他把这个parent group group group交给他的super就。这个group进行处理,同时把你传进来的charter group付给当前的这个charter group。
20:04
OK,就这样一个原理,好,紧接着我们继续往下追踪。最后他添加了一个channel,这点我要说明一下啊,加China,其中其中参数是class对象引导类,将通过这个class对象反射创建channel。Factory。他创建一个干什么呢。哎,也就是说我们这个channel到底是谁来创建的呢?其实是靠这个China factory来创建的。那待会儿呢,我给大家看一下源码就在这里。然后添加了一些TCP参数,来,同学们,我把这句话给大家找到。来看一下我们的China到底是在什么时候创建起来的,我把断点呢下载我们的源宝宝。没问题,同学们跟上我的思路就可以了。好,这个地方我下一下,也就是说我们这个channel其实是在哪里呢?是在这个地方创建的,是靠这个China factory来给我们创建的,我在这下个断点。
21:06
好,我们来追一下同学们。追一下。先把当前调试关闭。先把当前调试关闭。然后呢,我们打开server,好,同学们。走起来,Debug。好的,大家看,我们放过这个断点。再放一个断点。再放一次断点。到这儿来了。大家发现,此时此刻,其实这个圈还是空的。对吧,好往下走一把。好的,那我们看China类型,大家有没有发现这个China类型是IO server China。对吧,因为你当前先是给你的这个服务器创建对应的channel。好,这个,所以说这是n IO server,它是靠哪个给你做的呢?靠的是这个China factory,而这个China factory大家看大家读的单词reflection反射的China factory看懂了没有。
22:13
诶,其实它是一个基于反射的。公这个方式来创建,来创建我们的这一个China,明白好,接着继续往下追。然后呢,再再添加了一个日志专属的处理器,Handle不说了,再添加China,注意这个时候呢,是China的handle。这个地方注意看,回到这边来,回到这边来呢,同学们要有兴趣看一下这个handler。这个handle,其实他是把这个handler交给我们这个。嗯,这个boss group相关的handler,而把下面这些handler交给我们worker group相关的handler就是它是这样关联的,我们呢,可以来。
23:03
啊,这个就这就咱们不去追了啊,这这这个不去追了,如果有兴趣的同学去看一下这个源码,我们可以往里面看一下走,大家看这里。哎,这个Z是handler。这这个Z,其实这个Z当前是哪一个呢?是我们。服务器端的。服务器端,它所以说它是把这个handler。就是如果你是通过handler这个方方式传立一个char handle呢,这个handleer它是跟我们boss,就是boss group关联起来的。好,接着继续往下追。最后呢,它绑定端口并组设置连接,最后main线程关闭。Factory这个finally,呃,Finally块代码将在服务器中关闭我们相关的资源,这是这段代码,我们接着再读它的下面的。这个处理器。我们现在来读读一下哪一块呢?同学们,我们来读一下它的这段代码就是。
24:04
E server handler这种代码我们来简单阅读一下,代码很简单,对不对?我就直接说了。同学们看到这是一个普通的处理器,用于处理客户端发货的消息。在这里呢,我们。简单的分析出客户端传过来内容,然后打印,最后发送客户端,呃,发送这个数据给客户端,就是这样子,大家看这里,他这里面没有做过多的事情,看到没有,他read。啊,如果说你有数据我就read啊不,他是read read的时候,其实它是把这个消息呢在write出去。是不是他是这样子来处理的,然后。就是我们这这样这样写的,就是说简单的解析出客户端传过来种,然后打印,打印过后呢,最终发送字符串给客户端。那现在呢,我们已经把ni它这个DEMO源码的基本作用分析完了,下边呢,我们来分析一下event group group它的这样一个过程是什么样的。
我来说两句