一个url加载的全过程

时间:2022-06-01 22:10:39

最近在进行前端面试方面的一些准备,遇到了一个经典前端问题,一个url从输入到页面加载中间到底发生了什么,以前也认真想过这个问题,但是当时回答的都不全面,现在来好好总结一下:

总体来说分为以下六个步骤:

1、DNS解析

2、TCP连接

3、发送HTTP请求

4、服务器处理请求并返回HTTP报文

5、浏览器解析渲染页面

6、连接结束

具体过程:

1、DNS解析

DNS解析的过程就是寻找哪台服务器上有我请求资源的过程,当你在浏览器中输入一个地址时,例如:www.baidu.com,其实并不是百度网站真正意义上的地址,互联网上每一台计算机的唯一标识是他的IP地址,但是IP地址并不方便记忆,所以互联网设计者需要在用户的方便性与可用性方面做一个权衡,这个权衡就是一个网址到ip地址的转换,这个过程就是DNS解析,就是域名到ip地址的转换

DNS解析是一个递归查询的过程

例如你在浏览器中输入一个www.google.com的IP地址,首先在本地域名服务器中查询IP地址,如果没有找到,本地域名服务器会向根域名服务器发送一个请求,如果根域名服务器也不存储该域名,本地域名会向com*域名服务器发送一个请求,依次类推下去,直到最后本地域名服务器得到google的IP地址并把它缓存到本地,供下次查询使用(自己计算机上的hosts文件就是域名到ip的一个映射,他可以不用去寻找网络上的DNS解析),,从上述过程中,可以看出网址的解析是一个从右到左的过程:com->google.com->www.google.com,但是你是否发现少了点什么,根域名服务器的解析过程呢?实际上,真正的网址是www.google.com,并不是我多打开一个.,这个.对应的就是根域名服务器,默认情况下所有的网址的最后一位都是.,即然是默认情况下,为了方便用户,通常都会省略,浏览器在请求DNS的时候会自动加上去,所有的网址真正解析的过程为.->.com->google.com->www.google.com

DNS优化

为了了解DNS的过程,可以为我们带来什么?上文中请求道google的ip地址,经历了8个步骤,这个步骤中存在多个请求(同时存在UDP和TCP请求),为什么有两种请求方式呢)如果每次都经过这么多步骤,是否太耗时间,如何减少该过程的步骤呢,那就是DNS缓存

DNS缓存

DNS存在着多级缓存,从离浏览器的距离排序的话,有以下几种:浏览器缓存,系统缓存,路由缓存,IPS服务器缓存,根域名服务器缓存,*域名服务器缓存,主域名服务器缓存

在你的chrome浏览器中输入:chrome://dns/,你就可以看到chrome浏览器的DNS缓存

系统缓存主要存在hosts文件中

DNS负载均衡

不知道大家有没有思考过一个问题,DNS返回的IP地址石佛偶每次都一样呢?如果每次都一样是否说明你请求的资源都位于同一台机器上面,那么这台服务器需要多高的性能和存储才能满足亿万请求呢?其实真是的互联网世界背后存在成千上百的服务器,大型的网站甚至更多,在用户眼里,它需要的只是处理它的请求,哪台服务器处理并不重要。DNS可以返回一个合适的机器的IP给用户,例如可以根据每台服务器的负载量,该机器离用户地理位置的距离等,这种过程就是DNS负载均衡,又可以叫做DNS重定向,大家耳熟能详的CDN就是利用DNS的重定向技术,DNS服务器会返回一个跟用户最接近的点的IP地址给用户,CDN节点的服务器负责响应用户的请求,提供所需的内容。

2、TCP连接

HTTP协议是使用TCP作为其传输层协议的,当TCP出现瓶颈时,HTTP也会受到影响

3、HTTP协议

HTTP报文是包裹在TCP报文中发送的,服务器端收到TCP报文时会解包提取出HTTP报文,但是这个过程存在一定风险,HTTP报文时明文,如果中间被截取的话存在一些信息泄露的风险,那么在进入TCP报文之前对HTTP做一次加密就可以解决这个问题了,HTTPS协议的本质就是HTTP+SSL(or TLS)。在HTTP报文进入到TCP报文之前,先使用SSL对HTTP报文进行加密,从网络层结构看他位于HTTP协议与TCP协议之间。

HTTPS过程

HTTPS在传输数据之前需要客户端与服务器进行一个握手(TLS/SSL握手),在握手过程中将确立双方加密传输数据的密码信息,TLS/SSL使用了非对称加密,对称加密及hash等,HTTPS相比HTTP,虽然提供了安全保证,但是也势必会带来一些时间上的损耗,如握手和加密过程等,是否使用HTTPS需要根据具体情况在安全和性能方面做权衡。

HTTP请求

发送HTTP请求的过程就是构建HTTP请求报文并通过TCP协议中发送到服务器指定端口(HTTP协议是80/8080,HTTPS端口是443).HTTP请求报文由三部分组成:请求行,请求报头,请求正文。

请求行

格式如下:

Method Request-URL HTTP-Version CRLF

eg:GET index.html HTTP/1.1

常用的方法有:GET,POST,PUT,DELETE,OPTIONS,HEAD

请求抱头

请求报头允许客户端向服务器传递请求的附加信息和客户端自身的信息。客户端并不一定特指浏览器,有时候也可以使用测试工具等

常见的请求报头有:Accept,Accept-Charset,Accept-Endding,Accept-Language,Content-Type,Authorization,Cookie,User-Agent等。

Accept用于指定客户端用于接受哪些类型的信息,Accept-Encoding与Accept类似,它用于指定接受的编码方式。Connection设置为Keep-alive用于告诉客户端本次HTTP请求结束之后并不需要关闭TCP连接,这样可以使下次HTTP请求使用相同的TCP通道,节省TCP连接建立的时间。

请求正文

当使用POST、put等方法时,通常需要客户端向服务器传递数据,这些数据就存储在请求正文中,在请求包文中有一些与请求正文相关的信息,请求的数据格式一般为json,这时就需要设置Content-Type:application/json.

4、服务器处理请求并返回HTTP报文

这些就是后端工程师眼中的HTTP,后端从固定的端口接收到TCP报文开始,这一部分对应编程语言中的socket。它对TCP连接进行处理,对HTTP协议进行解析,并按照报文格式进一步封装成HTTP Request对象,供上层使用,这一部分工作一般是由WEB服务器去进行,我们使用过的W恶霸服务器又Tomcat等

http响应报文也是由散步分组成的状态码、响应报头、响应报文

状态码:

状态码是由三个数字组成的,第一个数字定义了响应的类别,且有5种可能取值:

1xx:指示信息-表示请求已接收,继续处理

2xx:成功-表示请求已被成功接收

3xx:重定向-要完成请求必须进行更进一步的操作

4xx:客户端错误-请求的语法错误或请求无法实现

5xx:服务器端错误--服务器未能实现合法的请求。

响应报文:

服务器返回给浏览器的文本信息,通常HTML、css、js、图片等文件就放在这一部分

5、浏览器解析渲染页面

浏览器收到HTML\CSS\JS文件后,它是如何把页面呈现到屏幕上的?

浏览器是一个边解析边渲染的过程。首先浏览器解析HTML文件构建DOM树,然后解析CSS文件构建渲染树,等到渲染树构建完成后,浏览器开始布局渲染树并将其绘制到屏幕上,这个过程比较复杂,设计到两个概念:reflow回流和repain重绘。DOM节点中的各个元素都是以盒模型的形式存在的,这些都需要浏览器去计算其位置和大小等,这个过程称为relow,当盒模型的位置大小和其他属性,颜色,字体确定下来之后,浏览器便开始绘制内容了,这个过程称为repain,页面在首次加载时必然会经历reflow和repain。这个过程是非常消耗性能的,尤其是在移动设备上,他会破坏用户体验,有时会造成页面卡顿,所以我们尽可能减少reflow和repain。

js解析是由浏览器中的js解析引擎完成的,js是单线程运行,也就是说,在同一个时间内只能做一件事,所有的任务都需要排队,前一个任务结束,后一个任务才开始,但是又存在某些任务比较耗时,如IO读写,所以需要一种机制可以先执行排在后面的任务,这就是:同步任何和异步任务,js的执行机制可以看作是一个主线程加上一个任务队列,同步任务就是放在主线程上执行的任务,异步任务是放在任务队列中的任务。所有的同步任务在主线程上执行,形成一个执行栈,异步任务有了运行结果就会在任务队列中放置一个事件;脚本运行时先依次运行执行栈,然后会从任务队列里提取事件,运行任务队列中的任务,这个过程是不断重复的,所以又叫事件循环。

浏览器在解析过程中,如果遇到请求外部资源的时候,如图像、js文件\css文件deng ,浏览器将下载该资源,请求过程是异步的,并不会影响html文档进行加载,但是当文档加载过程中遇到js文件时,html文档会挂起渲染过程,不仅要等到文档中js文件加载完毕还要等待解析执行完毕,才会继续html的渲染过程,原因是因为js有可能会修改dom结构,这意味着js执行完成前,后续所有资源下载是没有必要的,这就是js阻塞后续资源下载的根本原因,css文件的加载不影响js文件的加载,但是却影响js文件的执行,js代码执行前浏览器必须保证css文件已经下载并加载完毕,这也是在head中为什么先用link引用css文件,再去加载js文件的原因.

web优化

了解上面过程的目的就是为了Web优化,在谈到Web优化之前,我们回到一个更原始的问题,Web前端的本质是什么?我的理解是:将信息快速并友好的展示给用户并能够与用户进行交互,快速的意思就是在尽可能短的时间内完成页面的加载,试想一下如果你在淘宝购买东西的时候,淘宝页面加载十几秒才显示出物品,这个时候你还有心情去购物吗?怎么快速完成页面的加载呢?最简单的答案就是参照雅虎34条军规,这34条军规实际上就是围绕请求过程进行的一些优化方式。

如何尽快地加载资源呢?答案就是不能从网路中加载的资源就不从网路中加载,当我们合理使用缓存,将资源放在浏览器端,这是最快的方式,如果资源必须从网络中获取,则要考虑缩短连接时间,即DNS优化部分,减少响应内容大小,即对内容进行压缩。另一方面,如果加载的资源数比较少的话,额可以快速的响应用户,当资源到达浏览器之后,浏览器开始尽心那个解析渲染,浏览器中最耗时间的就是reflow,所以围绕这一部分可以澳旅如何减少reflow的次数。