00:00
好了同学们,那这节课呢,跟大家来聊一聊这个高并发系统的静态化资源的这种方案啊,这是处理高并发的这种呃需求的一个利器啊,其实处理高并发呢,无非也就是做缓存,然后资源静态化,然后再有就是把这个呃节点服务器的节点拉近于用户,那我们在这儿呢,跟大家来聊一聊资源静态化,因为前面呢已经给大家讲了。嗯,反向代理也讲了这个,呃,压缩这个请求数,压缩这个传输的数据,都是为了提高系统的这个传输速度的,那么这个资源静态化呢,它能够很明显的能够减少我们的计算啊,相当于把这个原本的这些这个呃应该传递到后端这些请求,然后把它给缓存下来,也是一种缓存这种呃这种方式吧,呃跟大家来简单的来画张图来看一看吧,比如这是我们的客户端。那我们现在所学到的知识呢,他还是要通过NG,然后做反应代理,把用户真实的意图请求,然后呢,呃,带到我们的这个后端的,或者叫上游的这些,呃,计算服务器上。
01:15
在这边呢,会做一些计算,比如说我们想要查看呃,我当前的这个,呃,这个账户余额对吧,比如说我想要去登录我的系统啊,再比如说呢,我想要看看呃,附近呢,呃有哪些这个美食,或者是现在能点的这些外卖啊,把这些请求呢,我们简单的归类一下,其实在这块呢,就可以做一些优化。我们现在讲的这个资源静态化呢,这是非常极其以及特别常见的,呃,这种解决方案几乎在所有的高并发系统里边都有,尤其是这些,呃,高并发的这种电商系统,你像淘宝,京东,拼多多啊,都会有这种资源静态化的情况出现。那么资源静态化,就能够把我们原本需要呃计算的一部分的这些请求给它,给缓存成文件,落地到我们,落地到我们的前端这个N这个字里,那比如说我想要看看附近的美食,那需要一个列表页,那这就会展示这个商户啊,对吧,那这些商户的列表它并不是每次都查询出来的。
02:18
啊,有同学可能想啊,那如果加一个或减一个,那这会儿呃,这个列表会不会变,那对,那这会儿就会涉及到这个。一致性的问题,这种请求呢,是读请求。你列表或者是这个详情页。为代表的这种,呃读请求或者叫get请求,它并没有向服务器端提交什么数据啊,当然说提交数据也是可以缓存的,我们在这儿呢,先做一个典典型的这种案例,呃,就是商户的列表页,或者是这个电商的这个详情页,展示商品的详情,大家要知道在一个电商系统当中。
03:01
并发请求最高的是什么位置?很多同学可能会想到是是不是我们站点的首页啊,啊,其实并不是啊,其实是这个并发量最高的呢,是这个我们商品的详情页,比如我们点开京东,以京东为例子啊,比如我想要,呃,比如现在电脑内存有点不太够用了,我想要找一个内存条,那第一种方式呢,我就在这分类里边去找,对吧?啊,我先找电脑,你看我的这个行为轨迹,首先第一下呢,我打开了它首页,这是第一次请求,第二呢,我去找这个电脑配件。比如找内存。这样他就打开了一个列表页,对吧,然后在内存这页里边我看了看,好像没有我太需要的,然后在内存这呢,我去筛选一下,比如我想看DDR5代的。对吧,然后再看一下这个,呃,内存频率是吧,4800。这会儿呢,就看到了很多的这个这个这个这个呃商品,呃,在这个列表里,注意我在列表页里刚刚刚刚点了两下,这是我的行为轨迹是吧,然后在这里边儿有很多我就开始看了啊,1400多的,这是多大的啊,它是16G乘两根。
04:14
对吧,在这里边还有它的这个紫的这个一些商品还可以点,诶我再看看这个多少钱,然后我再看看拉下去看看它的这个商品的详情,OK,这是金士顿的呃,货比三家嘛,呃,然后点开三星的看了看。对吧,啊,你会在这个列表页里点好多这个,呃,具体的这些产品啊,再有就是呢,另外一个入口就是搜索对吧,比如说我想要找这个笔记本内存。然后这有一个,呃,又出来一个列表,在这个列表里边呢,呃,我再点开看,再点开看,你可能打开一个一个列表页,呃,可能会呃打开多个这个商品详情页,呃再有就是很多的这个第三方的这些平台有可能把他的商品啊推荐出去。
05:02
对吧,有的能够赚佣金,有的是这个啊做广告啊,点开之后呢,直接就是某个商品,它并没有通过首页或者列表页,所以我们这个电商系统当中,并发量最高的就一定是这个详情页,其次呢就是列表页,然后再有呢,就是我们的首页和一些其他的广告页页,对吧?那我们在这这个详情页呢?呃,在展示的时候,传统的做法呢,就是把请求打到NGS反向代理过去,到我们的这个上游服务器,从数据库里边去。把这个商品的详情给它给拉出来,对吧,然后再展示,那在这我们说这个资源静态化这一步呢,能够极大的提升我们的系统的并发量,它的这个提升的点就在于我们把数据从数据库里拉出来之后,这份数据。这份动态数据,我们可以把它生成一个静态页面。这个呃,技术或者这套方案一点都不稀奇啊,在这个十几年前呢,很多的这个系统或者项目呢,都这么做,而且也不只是电商项目,对吧,现在是电商用并发量比较大啊,还有很好多这个新闻门户,你像网易啊头条,他在展示一些新闻的时候,这新闻的详情页也是一个道理,你列表呢,点开一下,可能会点开好几个新闻嘛,对吧,这个新闻页和这个商品详情页其实是一样的。
06:28
像这种页面呢,我们在看的时候啊,它的这个变化呢,并不会特别大,对吧,但是一定会有一些这个数据,比如说商品的价格有可能会变了,对吧,然后有一些商品的描述有可能会变了,但变化一定不会特别大,那这样这种情况下。就特别适合这种资源静态化的方案,一次取出来数据,那么接下来呢,我去复用这个静态的页面,这个静态页面具体怎么生成大家知道吗?啊,如果你要是有学过Java的话,呃,Java里边不是有这个模板引擎嘛,像什么simif啊,Enjoy呀,包括这个呃,JSP等等这种这模板引擎的这个工作原理。
07:12
他是要经过训练的。模板啊,这模板引擎,这模板引擎呢,它是要经经历一层渲染的,对不对,在这模板引擎里边会有很多标签。用来去填充我数据库里的数据,这个渲染的过程相当于把这个数据和标签做了这个匹配,然后最终呢会以流的形式,几乎所有的这个模板引擎都是这样的,以流的形式呢,去输出一个静态页面。然后最终呢,有我们的这个we部容器,也是tomcat或者一些其他的we部容器啊,把它这个静态页面以流行式的静态页面。
08:01
在输出给客户端,就本质上来说,我们做那些Java项目,你的这个输出呢,本来它就已经是静态页面了,那么这会儿可以拦截这个模板引擎,一般的模板引擎里都有这个功能,你是要把这个渲染后的结果直接输出给我们的这个,呃。客户端,也就是web容器,还是把它输出到另外一个文件里。这就是他的基本原理啊,咱们这课呢不是讲Java,所以在这儿呢,就不不带大家去敲这些代码啊。给大家讲一下原理,这个输出还有一个方向,就是直接给浏览器客户端对吧?那我如果要是输出到文件里边,那么从数据库里查出来这些,呃,商品详情,我就直接可以把它落地成一个静态文件,这就变成了一个静态文件了。那么这会儿就可以把这个静态文件直接前置到我们的NG里。啊,这叫资源静态化啊,同时呢,它也是一层缓存对不对啊,下次再去取的时候,我直接去取这个静态文件就可以了,在后边我们如果学了这个N,诶不是在我们后边如果学了这个open之后。
09:15
这里面还可以再加一层逻辑对吧?啊,这层逻辑就是比如说我们的客户端。他在请求我们N这个词的时候,比如说去取某一个静态页面,比如这个item100.html。那去取这个静态页面NG呢?从本地去加载,如果本地没有的话,这会儿就可以通过NG,对不是通过op ret对NG做二次开发,如果要是没找到这个,呃,这个这个静态页面的话,那么接下来open ret会帮我们去。直接去连接数据库,跨过我们的这个这个这个这个这个呃,后端的这个嗯,应用服务器,像tomcat直接去连数据库,并且op ret呢,可以内置模板引擎。
10:09
然后把数据呢读出来,直接渲染给我们的客户端啊,同时还可以再去落地到本地的本地的磁盘里。啊,这看起来是不是就很神奇了对吧?啊,高并发的这种系统架构呢,会引入更多的技术啊,我们现在给大家讲的呢,也就只是冰山一角,在这主要给大家讲这个资源定态化,现在我们能够理解这个资源静态化的意义了嘛,啊一旦要是一个静态的页面啊,客户端打向in这找到这个文件,直接一个send啪就出去了。速度极快啊,首先反向代理呢,就得经过这个网络这个呃,请求传递啊,在在这个向后端传递的过程啊,这里边就已经浪费了时间了,即使是非常短的时间,那再有就是在这个后端应用服务器,你还得再让应用服务器去连这个数据库,才能够把这个页面给展示出来。
11:01
啊,这个可想而知,这个这个查询的这个延迟它会有多高啊,我们。如果请求量比较小的话,你小型系统这都无所谓啊,如果要是大型系统并发量极高的话。在这儿呢,绝对是一个可以优化的点啊,这就是资源静态化,资源静态化能极高的提高我们整体的这个系统的效率,也有很多现成的这个,呃,组建或者是直接的这种这个开源项目,我们可以拿过来用,就是生成的这套方案啊,其实原理也都一样。那么我们生成完这个静态页面,我们接下来再看,那么就落地到这一个NG里吗?肯定不行,对吧,因为N这个它如果要是单个节点的话,那如果它要是出了故障,那这会儿我们整个系统都不可用了,所以NG也一定要搞成集群化的,对吧,我们我们的主题呢,讲的就是扩容,那N这个搞成集群化的时候。这会儿就有一个问题,我们的资源,也就是我们这个静态页面啊,他要在多个NG上落地那样才好,对吧?啊,那如果要是在这个NG上有的,这个静态页面这里边没有,那怎么办?那是不是要有同步的过程?
12:18
呃,那么这个同步的过程,我们需要通过呃,一系列的手段才能够达到,最简单的来说呢,在Linux上有这么一个呃小工具,非常好用,有好多年了,叫RSYNC。这个工具呢,就能够帮我们去把一台NG上的文件呢,给它给同步到另外一台NG上,也就是我们在后期的生成静态文件的时候呢,只需要往一个NG里去生成也就可以了,那么这一会儿它就成了种子了,就像我们呃养猪一样啊,这是种猪啊,一般种猪呢,它待遇伙食都比较好,所以就不让客户端直接去请求我们这个种猪。对吧,让客户端呢。
13:00
去请求他下出来,这个崽儿也是我们在在这个种猪的前面呢去。呃,部署很多的这个应用服务器去满足客户端的请求。然后这个种猪呢。我给它加个颜色。这个种猪啊,它向多个前端的NG去同步就可以了啊,不让它接请求,这样呢,它的这个压力会小一些啊,甚至呢,在这上面呢,我们也可以。不去部署这个NG,相当于我们在啊使用CDN的时候,这是云服务器啊,所有的数据呢,都往这一个里边写,然后他再分发到集群里边啊,这是这个基本的这个解决方案,然后还有就是一般的这个页面里边啊,它都比较复杂,我不可能把整个页面全部都生成到一个文件里。换句话说,这页面里呢,可能有一些动态的数据,比如说现在累计评论20万家,对吧,现在的价格。
14:02
还有这个啊,比如我购物车这个状态,把当前这一个这个页面全部缓存到一个文件里边。嗯嗯,那这样的是非常不好的,或者说呢,有的时候可能我们根本就做不到。对吧,啊,你像购物车还有当前登录状态,所以这会儿呢,就有一些。引用进来啊,我们就可以这么去做。呃,一个静态的这个页面,比如item.html。啊,里边包含了这个三部分内容,第一部分内容呢,就是。真正的这个内容。针对于当前这个item啊,当前这个资源的这个具体的内容,这是从数据库里针对于他的ID查出来的,第二部分就是关联的内容。啊,关联的呢,像一些呃推荐位啊,像一些这个呃,这个这个这个商品的评价,这都属于一些关联的,关联的内容啊,它不在当前的这个表里边,如果你做过这个电商的话,你要知道啊,对吧,你的这一个这个item存在也就是存在的这个PU对吧,还有一些这个呃,一些商品的详情,像边上这个推荐呢,这肯定不是。
15:22
对吧,像这种资源呢。一般来说呢,我们都会去引用。啊,这些呢,也一般都是动态资源,我们没法去直接把它生成成静态的这个页面啊,然后还有这个第三种情况呢,就是一些固定的内容,比如说啊,我的这个头,我的这个尾,包括这个整个页面的CSS的样式,你像头和尾。Header每一个页面里都一样,那我首先是没有必要把它生成到每一个文件里,那再有其次呢,就是一旦有一些改动的话,那这里边所受影响和波及的这个页面就会非常非常多,这是啥意思?
16:08
比如说头和尾,尾部呢,比如说我现在COPYRIGHT2022年对吧,那如果到2023年了之后,你把这个copyright给它写到内容里边了,并且给它生成出来了,你要更新的变成2023的话,你要把我当前服务器里边所有的这个呃,和它相关的页面全部都给。更新一遍,这是非常非常消耗资源的。有的时候。呃,这个呃,你的你的这个页面比较多啊,比如像京东几亿个页面,你这么去几联关联一下,呃,然后再去,呃,全部去。更新页面里的内容,这是非常非常难受的。然后这种固定的资源呢,我们就可以把它给抽取出来啊,你像写写Java代码就有这种这个这个呃封装继承多态对吧,那我们这些这会儿就可以把这个相同的东西呢,给它给抽取出来,抽取到一些,呃抽抽取一些这个固这个固定的,然后这个共用的这些资源,然后呢,单独生成一些静态页面。
17:13
共用的。注意这会儿生生成出来的呢,它也一定是静态的,那我们再看一看,那么这三部分内容怎么有机的把它关联起来,展示到一个页面里呢?这里边儿有很多方法,大致分为两类,第一类呢是前端合并。第二类呢,是后端合并,前端合并呢,呃举个例子就是I frame,或者是这个,呃,通过javascript或者是HTML这种方式啊,去填充页面的内容啊,比如说这个用JS,我在这inner HTML对吧,我把另外的这一个这个呃静态的资源我给它进来对吧,还有这I frame,我直接在这切一个I frame,还有就是像这个。
18:03
呃。一些这个这个这个点击操作,我点了之后再去加载对吧,这是全都是通过前端把我这些内容全部都给它合并到一起的这种方式,你像点击就是这个商品评价,本来它没显示对吧,我可以点完之后呢,这加一个loading的动作,然后呢去异步再去给它加载进来,那本质上它也不是在一块内容里。对吧,这是前端的合并方式。前端的合并方式呢,没什么问题啊,它比较节约资源,节约的是什么资源呢?节约的是服务器端的计算资源,浪费的是这个请求数。也不能叫浪费啊,叫消耗吧。它需要消耗更多的请求数,对吧,比如我I frame,我这页面里边呢,有五个I frame,那它就得再去额外的I frame,再通过I frame里边这个连接再去向我们的服务器去请求五次,对吧?这是前端合并啊,这个大家都比较好理解,这个后端合并就可以通过我们的NG格式,呃,把一些动态的和静态的资源呢,在服务器端直接给它合并好。
19:18
啊,这就有点像我们刚刚给他讲的这个con这个模块啊,你可你要同时请求三个这个,呃,CSS,那我给你合并成一个,你直接拿走不就可以了吗?它不只是能合并这个CSS啊,还可以去合并这个静态页面,这叫ssi这项技术。这个和con呢很像,但它不是一个模块啊,这是N的官方模块。那么我们就以这两点,一个是这个呃,合并输出,还有这个集群同步来给大家讲这个资源静态化,至于这个呃。页面生成这种方案,大家可以去额外的去查一些资料啊,或者是有有机会的话,后边我再给大家具体去讲怎么去生成和管理这个呃,静态这个静态页面啊,这就是咱们的这个资源静态化啊,资源静静态化的方案呢,还不只是这些啊,真正详细的细节呢,还会有很多,我们先呃给大家。
20:20
嗯,起一个头啊,先开一个头,我们先从这儿呢,一步一步的再往下去延伸啊。呃,再有就是这个一致性的问题,在页面里边呢,有很多这种,你像这个299啊,这是价格,这就很容易变,像这种这个比较容易变的这种。东西啊,或者是这这种这个这个这个数据,我们一般就不把它生成到静态页面里,因为你生成生成完之后再再次重新生成的时候。呃,磁盘的IO还有计算都是都是会有损耗的,文件越多,那你需要重新生成也就越多,服务器越多呢,就同步的这个过程呢,也就也是越多。
21:01
所以这种这个变化比较多的,还有一些动,稍微有一些动态请求的,我们尽可能的呢,就把它呃,以异步加载的方式给它给加载进来,不参与这个静态资源的生成啊,你像这个我的购物车,这肯定不能给它生成成静态资源,对吧,那怎么让它展示出来的,用JS去异步加载就可以了,对吧,还有登录状态这种,再有就是像京东的首页这种。啊,在生成静态页面的时候呢,可以只生成一个骨架,然后我们再去配合这个CDN,以及一些呃,额外的一些这个呃。处理啊,先蒸熟出来骨架,再让他去一步加载,让他一步一步来啊,这样呢,嗯,它的这个。呃,并发量啊,它的效果也会更好一些啊,尽可能的不要把或者或者是原则上呢,就不应该把这个和动态相关的一些资源呢,给我们生成了静态页面里,首页里边有很多这个推人系统推荐出来的东西,对吧,你肯定不能写嘛,因为千人千面的系统,每个人看见都不一样,是吧?呃,这是他的原则啊,就一定要保持一致性,保持保证这个一致性的问题。
22:11
呃,再有就是如果要真正的要写进去一些数据了,呃核一致性问题又避不开这种情况,那么我们怎么办啊,一般来说呢,我们还可以通过这个呃两步提交这种方式来解决这个问题。什么叫两步提交呢?咱们就以这个价格为例吧,假如说我们就必须得把这个价格写到这个静态页面里,那我就写进去了,那它一旦要是后端数据库里的这个价格变了,这个降价了或者涨价了,对吧,那用户看见这个页面了,它没有变,那这时候我们怎么办?啊,你可以两步去校验,就是用户在真正提交啊,加到购物车这一步,或者真正在结算那一步,这一步呢,就不要再静态化了啊,而是真正的去后端数据库里边呢,把这个真实的价格再给它展示出来,在结算的时候呢,明确的告诉我们的用户把这个真正的价格是多少啊这种方式呢,能够给我们这种静态化这个,呃,资源一致性不足的这个问题啊,提供一次补偿啊,有一点补偿的这种机会。
23:13
啊,当然这个方案还有很多,我们就不一一细讲了,那接下来给大家来讲这个和NG相关的啊,后端的文件合并输出,这个合并输出啊。
我来说两句