00:00
那么好,我们接下来看一下这张图啊,首先呢,我们NG先接到这么一个请求的报文,这个报文呢,它是二进制的形式,然后在N内部呢,会把它反序列化成它可读的这种文本,也是我们刚刚看到这种可读的文本啊get方法HTp1.1这些,然后去逐行去解析,他先解析完这个,呃,第一行的这个,呃一些请求的一些呃信息之后呢,就开始进入这个header和body的处理阶段。那么在这个阶段的时候。我们的服务器端,呃,这个会逐一请求,它会先处理请求头啊,请求头里边包含了一些这个,呃,比如想要保持什么协议,想想用这个keep alive等等等等这些信息,所以他需要先请求,先处理这个请求头,等处理完这个请求头之后呢,去处理这个请求体,在处理请求体的过程当中,因为用户有可能会上传比较大的文件。啊,然后在这儿呢,我们就可以呃,去在读取这个文件的时候呢,设置一层缓冲区,这个缓冲区是用于缓冲已经读到的客户端向我们提交上的这个文件啊在。
01:16
在读取文件的时候,它一定是一点点读的,那么在读的过程当中,我们刚才说的是文件啊,其实就是他请求的这个body,在读这个body的时候,那么这会儿除了这个client body buffer size。啊,可以去配置一下,呃,我们在NG的呃,内部的缓冲区,对于读取这个body可以使用多少个多少呃空间去缓冲,注意不是缓存啊,在这这节课里,我们讲的一切都是缓冲,不是缓存。那么在缓冲的过程当中。它会一点一点去读取用户提交上来的数据,那么在这额外就有另外一个配置,就是process request buffering。这个配置就表明了我们在读取的过程当中,要不要向我后端的或者叫上游的。
02:06
服务器直接发起请求。啊,如果要是on的话,它会等待我们把这个嗯。Body,用户提交上来的body完全读完之后,然后再去做反向代理的操作。如果这个process在呃,Request buffing,我们把它配置成了off,那么我们一旦接到用户请求之后,我就可以一边读取body。一边读一边向上游服务器发起请求,这是并行操作啊,然后这个。请求的过程当中呢,我们,呃,在这呢,可以先可以看到啊,它会先去选择这个upstream,我们所配置的这个服务器列表里,我们先去选择一个服务器,它默认情况下是以链表的形式轮询去选择的,也是我们之前这种配置我们什么都没写的情况下。
03:01
就在这呢,标记了几个server,它会在我们的这NG里啊,被映射成一个链表,那在读取链表的时候,它就可以通过下标一个一个的顺序往下读,这样效率会更高啊,那么轮询的一个一个往下去读,把服务器选出来之后呢,在这会儿NG个它是全异步的形式去处理的用户请求。他会先去向我们的。呃,操作系统的1PO的事件队列里先加入一个这个连接请求的,呃,这种事件注册同时啊,在读取完报文的时候,或者说在准备读报文的时候,已经,呃已经同时向我们这个一事件同时注册了回调函数。如果学过这个网络编程的同学,你应该知道,在epo也好,或者是Java的NIO里边也好,所有的这些数据,呃读取,网络连接建立,包括网络连接,网络连接断开,都是以这个事件的形式触发的。
04:08
啊,它触发事件之后呢,我们就可以去执行我们回调方法,或者说回调函数里边这些内容了。啊,那么我们先去向这个一里边去加入这个回调函数,以便在比如说建立完三次握手之后,可以触发回调某一个回调函数,然后呢,我们去呃这个处理它建立完连接之后啊,我们可以去处理一些事情,当连接呃真正建立完了,会触发一个可写的事件。也就是像可以像我的上游服务器真正把网络连接建立完成了,我已经可以向这边去写入数据了。啊,去写可写的状态时候,还会再去触发一个事件啊,在触发事件的时候,它没有任何的这个阻塞或者同步的概念啊,只有在触发事件之后,系统会向我们的NG个呃这个发送这个信号,然后NG才会去调取我们的这个回调函数啊,调取回调函数之后再去执行,在执行的过程当中。
05:09
我们就可以去向我们的上游服务器啊,去发送我们的这个真正客户端带过来的请求了,在发送的过程当中啊。我们呃之前还学习了配置这个呃,Keep alive的啊,包括这个呃,Set header这一系列操作,在在我们真正向服这个上游服务器发起请求的呃过程中,我们还可以去配置这个东西叫set header啊,这已经写了,就是这个set header。这个set header就是把用户,也就是客户端浏览器向我发送的请求,呃,我们在转发的时候可以额外的去增加一些我们想要带过去带到上游服务器里边的黑点啊,然后再把这个呃,HTTP请求再打包成这个,呃。标准的这个二进制的格式,再发送给我们的上游服务器啊,发送过去之后。
06:05
就是写可写事件这个触发完成,我们已经把这个呃,我们的HTP报文已经写给上游服务器了,由于所有的这些操作全部都是异步的,那么上游服务器的处理完结果之后,会返回结果给我们的NGNG同时还是通过这个E的事件触发啊来传达传递信号,让我们的这个回调函数来处理。上游服务器给我们返回的数据啊,在此过程当中。我们的N的进程是一直处于伺机待发的状态的啊,大家知道NX是多进程同时运行来处理这个业务逻辑的啊,也就是我们那个worker进程啊,它并不是说有一个进程去处理一这个,呃,一个请求,那么他就处这,那么他就在并行的时候啊,处理不了第二个。啊它而是这个它在处理的时候呢,更多的是呃在一个进程内呢,开启了更多的这个线程去处理这个呃,每一个这个函数去读,去写,去处理任何的事件,这样呢,它的并发能力呢,会这个这个呃更加的高。
07:17
那么在呃。我们的上游服务器处理完成这个,呃,我们的这个代理服务器的这个,嗯,请求之后。把结果返回给我们的这个NG,也就是代理服务器这会儿在读取上游服务器的数据的时候,这里边有这么一个配置叫per buffering on。这个配置指的是我们的,呃。上游服务器返回的数据我要不要缓冲?这里面就涉及到了一个问题,上下游的速率不一致。大家想象一下,我们的客户端,一般来说都是我们的手机啊,或者电脑的浏览器,那这个呃,接入互联网的网速啊,它是我无法控制的,或者说它不稳定,有时候时快时慢,那我发送一个请求,想要一个文件啊,那这个文件。
08:17
想要传递给我们的真正的终端用户的话,他是要通过网络的,就是极有可能我们在向客户端发送数据的时候呢,这个速度呢,达不到这个这个峰值,也就是说速率跑不满。那么上游服务器这个可就不一定了,通常来说我们的上游服务器是在我们局域网里的,在局域网里的速度是非常非常快的,但游客非常容易就把我们这个带宽给跑满了,比如说你是呃,千兆网卡或者万兆网卡啊数这个数据呢,一瞬间就传到我们的这个NG里了,那么NG又作为反向代理服务器,它需要把这份数据传递给我们的客户端,那首先我们的上游服务器如果返回的数据包。
09:00
比较大的情况下,比如这里边有一个咱们极端一点有个20G的数据,数据文件,你的请求就是一个盖的请求,那我给你返回一个电影,那这个电影呢,是高清的,是20G大小,那么这20G大小的文件,我们NG要怎么处理,它要一次性的把这20G的文件全部都加载到我们的。这个这个NG的内存当中,然后再慢慢的发送给我们的客户端吗。很显然的,不是的啊,首先要在我们的这个,呃。在我们的这个这个N里有这么一个配置,刚才的刚才给大家说的就是pro buff这个配置,如果把它配置成off,那么它就在这个过程当中呢,完全不做缓冲了,注意这不是缓存,它是缓冲在读完文件之后,读多少给你传多少。传完之后再慢慢的去读啊,一点一点的,一边读着一边给你发着,那么这样上下游的速率基本上就一致了,就是上游的速度呢,它比较快,但是下游呢,虽然说比较慢的话,虽然说情况呢比较慢。
10:05
呃,那我可以这个慢慢的去读,那么这样的话带来的最大的坏处就是。我们会有毒的,这个线程一直被占用着,也是网络请求,这个网络它一直都中断不了。那如果这20级文件。我们从上游服务器N,这个从上游服务器读取过来,比如说他需要20秒,但是我要发送给客户端需要20个小时。那么这个,呃,我们像这个上游服务器这个网络连接,它就一直不能中断,因为你没传完,我这边也没有对吧,因为NG里它没有你需要多少,我给你去读多少啊,所以尽可能的这个我们可以去配置一下这个processing。把它打开,让上游服务器这份数据啊缓冲到N几的内部,然后从而断开这个网络连接,或者是复用这个网络连接。
11:00
啊,那这个。呃,一旦配置成on了之后。啊,那么我们就开始去读取这个上游服务器的数据,并且写缓写,写缓冲,写到我们的这个NG里,这里边儿有额外的一个配置叫pro buffer兹。这个配置后边跟两个参数,一个是32,一个是64。这三十二指的是个数,这64指的是大小,在内存中去分配32个64K大小的缓冲块,去缓冲我们这些这个数据,当然刚才我说的是20G啊,这是比较极端的情况,通常情况下上下游的速率不一致,也不一定有这么这个悬殊啊,比如说我们这个稍微小一点,比如就两三兆或者或者几百K的数据,这是非常常见的。那么下游的,呃,我们的客户端速率比较慢的时候,我们就可以请求上游服务器把数据拉回来放到我们的内存里边,然后慢慢直慢慢发给我们的这个客户端,从而呢,就可以断开和上游服务器的这个网络连接。
12:06
或者是让他去复用之前这个网络连接。那么往往哪写,就往这内存里写32个64K大小,那么如果说啊,要是。内存装不下,它写满了怎么办?因为我们已经proceed buffing,我希望他这个去帮我们去缓冲了,对吧,那么他就会尽可能的快速的把上游服务器里边的数据。啊,给我们这个。这个这个呃,这个读取到我们的内存里,一次性读完之后,然后等着呃客户端慢慢去读,一旦它又不够用了,这里边儿还有额外的呃两个配置。在这儿。因为这个图里边配置的实在是太多了,我就没往上加,咱们一边讲一边往上加。啊,那第一个呢,就是这个东西叫pro max temp file size。
13:01
内存写慢了没关系,我还可以往磁盘去写,对吧。就是这个配置。这个配置它,呃,限制了我们。往磁盘里去写入缓冲,比如像磁盘。写入缓冲的,呃,这个这这么组织一下啊,写入这个pro。Pass,读到数据的。向此番写入pass,嗯。这,这怎么。呃,这这这这这简化一下语言吧,就是读到数据向磁盘写入的。向磁盘写入的最大值啊,你这个往磁盘里写这个文件最大能写多大啊?就是这个啊,Process markx file size。
14:08
默认情况下呢,就是一个G大小啊,当然你这个文件如果要超过一个G的话,你再去调整调整是吧?啊以避免这个呃一次一次性的读不完,然后客户端也没下载完,然后我们在这慢慢的呃这个这个我们这个连接呢,还在这慢慢的这个这个这个这个持续的去读啊占用连接。然后另外一个呢,就是他写在哪儿。这个配置是这是是这个。Pass啊,是这个配置。这是向磁盘写入我们的这个,呃。缓冲文件的时候,它写在哪儿,我们可以直接去配置地址啊,它配置的格式呢,这比较特殊。这个是呃,具体的一个路径对吧,然后后边的跟一和二。这表示的是层级啊。
15:02
那他这么做的好处其实也就是在我们的磁盘上面建立更多的文件目录,然后更这个层级更深的文件目录。因为你在一个。呃,目录架如果要并发量比较高,那请求量比较大的时候,你想想那得创建多少个文件,就在一个目录架,因为在单一目录下呢,文件过多,那你在查找的时候呢,会非常不方便啊,然后它就可以建立多多级目录,多建立几个目录啊,那这样在某一个目录下,它存放的文件当你并放量比较大的时候,就不会特别多,因为目录也非常多,对吧?啊,这是这个。呃,存储的这个路径,还有这个,呃,针对于这个路径,我们会给它设置出来这个几几个层级的这个目录来存储我们的文件,然后另外还有一个配置,就是这个process time file right size,这指的就是我们像我们的临时缓冲区,也就是我们这个临时文件里去写入数据的时候,每次写多少,它不可能我一下呃给你写这个呃几几兆几十兆的文,这个数据文件像磁盘,因为这样的话会占用我们的这个系统的。
16:08
呃,资源会比较多,所以呢,我们就可以配置一下它这个向磁盘写入的这个缓冲。这叫。嗯。Right size啊,这是。向磁盘缓冲区写入。写写入时。写入十啊。一次。写入的大小啊,你不能一下写这个写写几昼进去啊。这是它的三个配置,我们给大家再重新捋一遍,首先呢,在process pass之后,你把请求转发过去之后,转发到我们上游服务器了,那返回来的数据,这是在处理的时候是比较麻烦的,这呢有一个配置叫per buffing on,那如果要是把它给打开了。
17:19
On的时候它会向磁盘去写数据,注意听啊,On的时候如果要是缓冲区大小不够用了啊,它会向磁盘去写数据,那如果要是大小还够用的话,那直接就给你中转过去了,这时在后边咱们讲调优的时候,这里边可以调优的一个点对吧?啊,那针对于不同的业务场景,你可以调整它这个内存缓冲区的大小,也可以通过增加内存去提升我们这个NG的并发量。当然也针对不同的业务是吧,有的时候你下载文件比较大的时候,往内存里边放,其实也不合适,对吧,然后如果它是off的话,那会发生什么,如果这个processing buffing变成了off。
18:00
那么接下来。这个内存缓冲区针对于我们上游服务器返回了数据,它的这个body部分啊,返回数据的这个部分。就不再缓冲了啊,但是呢,Header部分它一直都是缓冲的啊,这个配置叫process bar for size。啊,这个名字啊,看起来有歧义对吧?你看不出来它好像针对于header的,这也看不出来它是针对body的,但它确实就是这样,这pro baruff size,它就是针对于我们上游服务器返回来数据当中的header进行缓冲的。如果要是我们的这个,呃,Body部分的缓冲区,我们把它给关了,那么它就会利用header的缓冲区来缓冲一下上游服务器的这个数据啊,那如果要是hier这个不够,一般来说都不够啊。啊,除非你就是简单请求嘛,对吧,如果他不够的话,那么接下来他不会像磁盘去写这些临时文件。
19:02
啊,这是关闭的情况,如果开了的话它会写,如果关了的话,他就不写了啊。那我们在呃,咱们我们在这个这个NG的内部的过程当中呢,可以有这些配置可以配,那我们把它现在呢,呃,配到我们的这个呃,这个服务器上给大家看看,其实也看不太出来这个效果啊啊,因为现在咱们的这个并发量并没有啊。
我来说两句