前言问题:为什么很多站点第二次打开速度会很快?
前面我们已经说了tcp的一些流程,而http协议是建立在tcp协议基础之上的 http是一种无状态的丶允许浏览器向允许浏览器向服务器获取资源的协议,是Web的基础 通常由浏览器发起请求,用来获取不同类型的文件,例如html文件,css文件,js文件,图片,视频等.此外,http也是浏览器使用的最广泛的协议,要学好浏览器和前端,就必须要深入了解http协议
浏览器发起http请求流程
如果你在浏览器输入地址www.baidu.com ,那么接下来,浏览器会完成哪些动作呢?
1.构建请求
首先浏览器构建请求行信息GET /index.html HTTP1.1 get是请求方式,index.html是请求资源,http1.1是版本号(目前大部分还是http1.1,http版本以后介绍) 构建好请求后,浏览器发起网络请求,前面已经说过 由网络进程发起
2.查找缓存
在真正发起请求之前,浏览器会现在浏览器缓存中查询是否有要请求的资源.其中浏览器缓存是是一种在本地保存资源副本,供下一次请求使用的技术
当浏览器发现请求的资源已经在浏览器中缓存有副本,那么它会拦截请求,返会该资源的副本,并直接结束请求,不会去服务器上下载了.(其实这里有一个强缓存和协商缓存的方式来判断一下缓存是否过期,没有过期才会直接返回,否则过期了还要去服务器判定,这里只做简单描述) 这么做的好处有: 1.缓解服务器的压力,提升性能(获取资源的耗时更短了) 2.对于网站来说,缓存是实现快速资源加载的重要组成部分 当然,如果缓存查找失败,就会进入网络请求
3.准备ip地址和端口
先别急,在这之前先说说tcp协议和http协议的联系.因为浏览器使用的是http协议作用应用层协议,用来封装请求文本的信息,并且使用tcp/ip协议传输层发到网络上,所以http工作之前,浏览器需要通过tcp与服务器建立连接(准备工作要先做好嘛,不然之前做的都是白费) 也就是说http的内容是通过tcp/ip协议来传输来实现的. 流程大概是是这样:
服务器和浏览器建立一个tcp连接(连接建立阶段)->发送请求行(前面说过)->发送请求头->服务器响应请求行->服务器响应请求头->服务器回复内容(html,css,js,img文件等)->断开tcp连接
上面分为3个过程可以:连接建立阶段和数据传输阶段和连接释放阶段 我用的是访问www.baidu.com做例子,没有请求体之类的,有的网站有那就加上 好了,tcp前面我已经说过了,如果是看着我的之前的博客来的,那应该比较了解了,那么http是怎么请求的呢? tcp要工作,首先你得给他一个域名和端口号吧?域名和端口号从哪来呢? 对的.我们有一个url地址,可是url地址怎么变成ip地址和端口信息呢? 前面我已经说过ip地址是一个纯数字的逻辑地址,难以记忆.于是呼,就出现了域名(baidu.com)来帮助用户记忆,所以这个基于需求就需要把域名和ip地址做一个映射关系, 了解js的同学直接理解为map结构中的一对一的映射关系就行,这套域名映射ip的系统就叫做域名系统,简称**DNS **
DNS的具体作用
我们在网址栏输入一个地址,这个地址就是个域名,计算机其实是不认识这个域名的,因为底层只认识ip地址,而dns服务器就是将这个域名解析成ip地址,供底层去查找服务器所在的位置. DNS:
- 一个分层的DNS服务器实现的分布式数据库
- 一个使得主机能够查询分布式数据库的应用层
**分布式数据库系统:**通常使用较小的计算机系统,每台计算机可单独放在一个地方,每台计算机中都可能有DBMS的一份完整拷贝副本,或者部分拷贝副本,并具有自己局部的数据库,位于不同地点的许多计算机通过网络互相连接,共同组成一个完整的、全局的逻辑上集中、物理上分布的大型数据库 .(ps:和我们平时学的关系数据库不太一样,了解就好)
我们发送一个域名请求,它将返回我们一个与其主机名对应得ip地址,因为是分布式数据库,全世界有太多得ip地址,所以整个DNS系统是分散在世界各地,由很多台DNS服务器组成,这么说把,你可以把他看成一个小网络,每台dns服务器都存了一些数据
所以DNS查询就是简单来说,就是去dns服务器上问:’‘你知道这个域名的ip地址吗?’’ 不知道就去别的dns服务器上找,直到找到或者找不到
算了,我还是说清楚一点,之前字节面试问到了,但我没理解的那么深…所以芭比Q了 DNS服务器有3个层次或者说类型:
- 根DNS服务器.
- 顶级域DNS服务器
- 权威DNS服务器
根DNS服务器: 首先明确域名是什么,www.baidu.com,千万不要以为com是根域名啊,其实他是顶级域名,它的完整写法应该是www.baidu.com. 最后这个写的. 才是根域名 只是通常省略了 根DNS服务器的作用就是管理他的下一级,也就是顶级域DNS服务器,通过询问根DNS服务器,我们可以知道一个主机名对应的顶级域DNS服务器的ip是多少,然后根据这个ip去顶级域DNS服务器上查找
顶级域DNS服务器 除了com是顶级域名,常见的顶级域名还有cn,org,edu等.顶级域DNS服务器,也就是TLD(简称),提供了它的下级,也就是权威DNS服务器的ip地址
权威DNS服务器 这才是可以返回主机-ip的最终映射的玩意 我先告诉大家他们之间的关系,接下来我尽可能用我的语言简洁说出来
本地DNS 本地DNS服务器严格来说不属于DNS的层次结构,但是它有很重要. 每个ISP(互联网服务供应商)都有一台本地DNS服务器,比如一个居民区的ISP,一个大学的ISP,一个机构的ISP,都有一台或者多台的DNS服务器,当你所在的那个网络区域的主机发起DNS请求时,该请求先被发往本地的DNS服务器,注意本地DNS服务器只起到代理的作用,本身并不会存储相关太多的DNS映射,最多做一个缓存.定时会清除本地DNS将请求转发到DNS层次中
好了,现在正式讲流程了,我们给浏览器一个url地址,然后浏览器去查找浏览器中DNS缓存(浏览器本身有一个DNS缓存),浏览器DNS缓存中没有的话就去本地DNS服务器中查找, 然后呢就是一个递归+迭代的过程了
1.浏览器(主机假设是m.n.com)发起一个域名查询报文给本地DNS服务器,其中包含带查询的域名(假设是a.b.com) 2.本地DNS收到之后将这个报文转发给根DNS服务器 3.根DNS服务器主要com是顶级域名就将com对应的TLD对应的ip地址列表返回给本地DNS服务器 4.本地DNS服务器收到TLD的ip地址,将报文又向这个返回的ip发送 5.TLD收到查询报文,检测到b.com前缀,便向本地DNS服务器返回权威DNS服务器的ip地址 6.本地DNS服务器又向返回的权威DNS服务器ip地址发送查询报文, 7.权威DNS终于查询到了最终返回要找的a.b.com的ip地址 返回给本地DNS 8.本地DNS服务器将这个返回的结果ip地址做一个缓存,然后返回你的主机
好了 至此ip地址找到了,而且还做了缓存,一定时间内你再次发起这个域名请求是直接走缓存的 那么,问题来了?一定是这种递归+迭代的模式吗? …emmm好在我踩了脚刹车,还真不一定… 他可能不是每次都返回本地DNS的,而是本地DNS发送查询报文给根DNS服务器,而根DNS服务器直接去TLD查找… 这样就没有递归,只有迭代了 也就是迭代是一定的,递归不一定
ip地址拿到了之后,如果没有特别指定端口号,那么就是默认的http端口号80了,好了,说了这么多,现在终于可以发起请求了吧? 答案是还是不行!为什么?因为浏览器还有一个机制 chrome有个机制,同一个域名最多同时建立6个tcp连接,如果同一个域名下同时有超过6个的请求发生,那么多余的就要排队等待了,等到进行中的请求释放
好了 判断结束后,就可以正式建立TCP连接了(终于来了!呜呜呜~~) TCP建立之后(如何建立看我的上一篇博客) 浏览器就可以和服务器进行通信了,而http中的数据就是在这个通信过程中传输的 请求行:
GET /index.html http/1.1
请求头:
Host:源地址
Connection:keep-alive
Pragma:no-cache
Cache-Control:no-cache
cookie:...
....
首先浏览器向服务器发送请求行,告诉服务器我用什么方法请求的,请求url,http用的什么协议,这其实就是告诉服务器我请求的资源位置,如果是POST请求,还需要一个请求体,请求体里面携带数据传递给服务器.至于请求头的话,里面携带一些基本信息,源地址,连接形式,缓存,cookie,浏览器内核等
然后呢 然后就是
服务器处理HTTP请求
1.返回请求 一旦服务器处理结束,便可以将数据返回给浏览器,同样的 有一个响应行
HTTP/1.1 200 OK
响应头.响应体 首先返回响应行,包括协议版本和状态码 但是并不是所有的请求,服务器都会处理,对于一些无法处理或者内部的错误的请求,服务器回通过请求行中的状态码告诉浏览器 ‘哥们,你这活我干完了/我干不了’ 状态码大家伙可以自己去看看,那都是一些死记硬背的东西,背几个常用的就OK了 然后就是返回响应头了,里面有一些content-type(这个搞前端的大家伙都熟悉),set-cookie,之类的一些简单信息,发送完响应头之后,就回发送响应体, 响应体就是你需要的文件,比如html文件之类的
以上就是服务器响应浏览器的具体过程了
2.断开连接 通常情况下,服务器发送完了请求数据后,就要开始关闭tcp连接了,不过如果浏览器或者服务器在其头信息中加入了connection:Keep-alive 那么tcp连接在发送后就仍然保持打开状态,这样的话就可以继续通过这同一个tco连接发送请求,减少连接建立时的资源,时间的浪费 这些具体以后讲http版本的时候说
3.重定向 到这里请求流程似乎结束了?,不过还有一种情况必须了解,也是面试问的比较多的 你在地址栏搜baidu.com,打开的确实https:www.baidu.com,这两个url不一样,但是内容是一样的就涉及到了重定向的操作.你会看到返回的响应行中状态码时301,响应头中多了一个Location:https://www.baidu.com ,这就是告诉浏览器,我需要重定向到另外一个网址,而那个网址就是location中的网址,重新导航,这就是一个完整的重定向流程. 这个流程不是必然的.百度有,别的服务器可能没有这个处理,比如12306,你必须输入完整的12306才能打开
总结
我们开头提到的问题可以解答了,首次打开页面,需要进行tcp连接,dns查询,然后就是一系列数据请求,传输等,但是当我们第二次请求页面时,首先dns缓存已经给你缓存好,浏览器也会给你缓存一些静态数据,需要就直接从缓存拿了,所以第二次打开页面时,速度会快很多 浏览器缓存我下一篇博客具体讲,顺便方便自己理解
这篇的内容比较碎片一点,我也是想到什么说什么 大致分为8个阶段吧 构建请求->查找缓存->准备ip和端口->等待TCP队列->建立TCP连接->发起http请求->服务器处理请求->服务器返回请求->断开连接 期间还聊到了一点缓存,dns映射缓存就不多讲了,底层是一个hash表的数据结构和es6中的map底层结构一样,感兴趣的可以自己去看一看(我也没过多了解)
|