「一道面试题」输入URL到渲染全面梳理下-总结篇

10,379 阅读40分钟

要知道

此文是一道面试题,又不仅仅是一道面试题,你会发现,这题不论大厂小厂,都会问,为什么

因为它足够经典,连续写了三篇帖子,每篇都上万字,依然感觉不够细,涉及的点真的很考验一个人的知识覆盖率,还是多方面的考验,如果让我来面试的话,我觉得完全可以通过这一道题挖掘出面试者的基础知识储备量,延展性更是超强

SO,答好它可以让面试官眼前一亮,让你与众不同

此文是总结篇,没有看过前两篇的小伙伴建议先看看,然后自己总结总结,再来看这篇,因为前两文是为了能够看懂此文才写的

「一道面试题」输入URL到渲染全面梳理上-网络通信篇

「一道面试题」输入URL到渲染全面梳理中-页面渲染篇

如果你都看过了,那就来一块总结吧,首先,还请为我的疯狂码字点个赞再看哦,最近打字速度都快了不少 😄

回顾

本来这块儿会简单回顾下前两文知识点再进行总结的,还有一个思维导图,原本已经写的差不多了,大概有个1万字了,后来写着写着被我删了大半重新写了

因为某天心血来潮,想把整篇文章换成一面试的问答帖,写帖嘛,我比较喜欢 认真且随心所欲 ,就删了重来了,所以此文才会慢了些

下文会以一个面试官和面试者问答的过程来描述这些个问题,主体问题答完之后还会有一些比较常见的主体发散的问题,最近得空看完了电视剧 鬓边不是海棠红 ,看的说话都有点被带跑偏了,用剧中 老北京腔 来说就是 得,您瞧好吧!😄 ,好了,调侃完毕,开始正经了,干巴巴的万字小文来了,做好准备哦

首先请带入你自己,你就是一个面试者,仔细看每道题,先静心想一会,然后在心中回答,最后再看总结的答案 ( 此答案也不一定对,个人感悟,只给大家做参考,也望大家给予补充或指正 )

问(主体):输入URL到页面渲染都经历了什么?

个人觉得 ,不要急着回答,先思考30秒,在心中形成一个大致步骤的轮廓,先概括,然后再慢慢道来,注意节奏,中间也可以短暂停顿思考,面试官不会因为你想了一会就 pass 掉你,相反,你直接脱口而出一堆内容,会让面试官觉得你像是背课文

对于主体问题,写了两种回答,觉得需要注意两点来选择性回答,至少我这么觉得

面试官的状态

大致判断面试官是一个什么样的人,注意面试官这个人的状态,这很重要,通过对面试官当时状态的判断来决定精简回答或是轰炸式回答,这里的轰炸式回答不是说越多越好,说的是我们在回答的时候顺带牵出一些知识点来证明我们的知识量,但是不管怎样回答都要回答在点上,不要认为答得越多越好就扯一些有的没的,这大概就是察言观色吧

你的状态

你的状态就比较容易理解了,如果你对一些知识点掌握不牢靠或有些紧张,这个时候就不要死撑还争取回答的面面俱到了 (面试官面前不太懂硬装做什么都懂,容易引起些许反感),尽量精简,把你熟的地方多说一点,这样可以对面试官进行一个暗示引导,然后等待让面试官发散问你,通常你哪里说的多,面试官就会往哪个方向发散,如果你足够自信,那就尽情说好了,不在意他的发散,只要不说没用的就👌,绝大多数面试官对于这种情况应该都会喜欢

一本正经的轰炸式回答

面试官你好,这个问题是一个经典问题,我业余时间也有仔细阅读过一些相关书籍,做过一些总结,因为涉及到的知识点很多,所以可能会花一些时间,如果中间您有什么问题或者我的回答有不正确,还请您随时打断我,为我指出错误,谢谢

我觉得从URL输入到页面渲染大体上可以分为网络通信页面渲染 两个阶段

首先是网络通信阶段,在互联网中网络设备之间的通信都会遵循 TCP/IP四层协议,通过 TCP/IP 网络分层顺序与对方进行通信,分层由高到低分别为:应用层、传输层、网络层、数据链路层,我们浏览器输入URL也就是发送端会从 应用层 往下走,接收端也就是服务器会从 数据链路层 往上走,通常我们会用五层协议来解释,数据链路层这一层会分成物理层和数据链路层两层

浏览器输入URL

输入URL按下回车后,就进入了 应用层 开始往下走,浏览器会开一个线程来处理,先对URL进行解析,一般包括 ( 协议头、主机域名或IP地址、端口号、请求路径、查询参数、hash等等 ),然后打开网络线程发出一个完整的请求

应用层DNS解析域名

这其中DNS解析,也就是 域名或IP解析 是因为我们输入的URL通常都是一个域名,计算机不认识域名只知道IP,所以需要DNS解析通过域名查询得到对应IP,对于DNS解析时

  • 首先会查看浏览器DNS缓存
  • 没有的话就查询计算机本地DNS缓存
  • 还没有就询问递归式DNS服务器(就是网络提供商,一般这个服务器都会有自己的缓存,所以IP查询大多都在这里完成)
  • 如果依然没有缓存,那就需要通过 根域名服务器 和 TLD域名服务器 再到对应的 权威DNS服务器 找记录,并缓存到 递归式服务器,然后 递归服务器 再将记录返回给本地

应用层客户端发送HTTP请求

IP地址有了,应用层的客户端想看页面,就会发一个 HTTP 请求,HTTP 请求分为 请求报头请求主体 ,请求主体就是客户端要发送给服务器或者服务器返回给客户端的内容,请求报头比较重要,包含通信方式也就是请求方法 (POST / GET / INPUT / DELETE等)、URI、协议版本号以及请求头部方法(Accept、Cache-Control…)

传输层TCP传输报文

应用层 发送了一个请求后,为了传输方便,在 传输层 会把从 应用层 接收到的数据 ( 就是那个HTTP请求报文 ) 进行分割,并为每个报文编号后再转发给 网络层,编号就是方便服务器接收时能准确地还原报文信息,这里用到了我们常说的 TCP协议

TCP协议 会通过 三次握手 保证传输的安全可靠,也可以这样说,客户端在 传输层 开始和服务器通过 三次握手 建立 TCP/IP 连接

所谓的 三次握手 ,就是发送端先发送一个带有 SYN ( synchronize ) 标志的数据包给接收端,在一定的延迟时间内等待接收端的回复,接收端收到数据包后,传回一个带有 SYN / ACK 标志的数据包以表示传达确认信息,接收方收到后再发送一个带有 ACK 标志的数据包给接收端以表示握手成功,在这个过程中,如果发送端在规定延迟时间内没有收到回复则默认接收方没有收到请求,而再次发送,直到收到回复为止

也就是上一文说的

  • 小李 (客户端):您好,您是xx的面试官吗?

  • 面试官 (服务端):嗯嗯,是的,你是昨天投简历的小李吗?

  • 小李 (客户端):嗯嗯,是的,我是

网络层IP协议查询MAC地址

建立连接后 网络层 IP协议会查询 MAC地址 进行数据包的传输

通俗来说,IP协议 负责把各种数据包传送给接收方,因为要保证确实能传输到对方,所以需要确定接收方的 MAC地址 也就是我们说的物理地址,IP地址 可以和 MAC地址 通过映射表一一配对上,一个网络设备的IP地址可以更换,但是MAC地址一般是固定不变的,而 IPMAC 的解析过程则依赖于 ARP协议,它可以根据通信方的 IP地址 反查出对应的 MAC地址

因为一般通信双方是无法直接进行通信的(除非在同一局域网),会经过多台计算机或路由器来进行中转,所以也就需要 ARP 来一路确认下一个中转站,协助数据包的传输

数据到达数据链路层

找到对方的 MAC地址 后,就会将数据发送到 数据链路层传输,到此客户端发送请求阶段就结束了

服务器接收数据

而后接收端的服务器在 数据链路层 接收到数据包,再通过相反的方式将数据一层一层的还原回 应用层 ,这过程中包括在运输层那里通过TCP协议将分段的数据包重新组成原来的HTTP请求报文

请求到了后台服务器,一般来说会有统一的验证,如安全验证、跨域验证等,验证未通过就直接返回相应的HTTP报文,验证通过后,就会进入后台代码,此时程序收到请求,然后会执行对应的操作

如果浏览器访问过,且缓存上有对应的资源,就会与服务器最后修改时间对比,一致便返回304,告诉浏览器可使用本地缓存

服务器响应请求

服务器接收到客户端发送的HTTP请求后,会查找客户端请求的资源,并返回响应报文

另外现在很多网站都会有重定向功能,比如请求域名省去了 www.,它会给你重定向来添加上,这也就意味着第一次请求 HTML 的过程中我们是需要发起两次请求的

这样做的原因在于搜索引擎会认为 www.xxx.comxxx.com 是两个网站,从而造成网站排名下降,还有如果两个地址都有打开过,会造成多余 ( 双倍 ) 的浏览器缓存

服务器返回相应文件

请求成功后,服务器会返回相应的网页,浏览器接收到响应成功的报文后便开始下载网页,至此,网络通信结束

解析HTML构建DOM Tree

拿到服务器返回的网页后,首先,根据顶部定义的DTD类型进行对应的解析方式,网页的解析将会被交给内部的GUI渲染线程处理

渲染线程中的HTML解释器,将HTML网页和资源从字节流解释转换成字符流,再通过词法分析器将字符流解释成词,之后经过语法分析器根据词构建成节点,最后通过这些节点组建一个DOM树

这个过程中,如果遇到的节点是 JS 代码,就会调用 JS引擎 对 JS代码进行解释执行,此时由于 JS引擎GUI渲染线程 的互斥,GUI渲染线程 就会被挂起,渲染过程停止,如果 JS 代码的运行中对DOM树进行了修改,那么DOM的构建需要从新开始

如果节点需要依赖其他资源,图片/CSS等等,就会调用网络模块的资源加载器来加载它们,它们是异步的,不会阻塞当前DOM树的构建

如果遇到的是 JS 资源URL(没有标记异步),则需要停止当前DOM的构建,直到 JS 的资源加载并被 JS引擎 执行后才继续构建DOM

解析CSS构建CSSOM Tree

CSS解释器会将CSS文件解释成内部表示结构,生成CSS规则树,这个过程也是和DOM解析类似的,CSS 字节转换成字符,接着词法解析与法解析,最后构成 CSS对象模型(CSSOM) 的树结构

构建的过程中浏览器得递归 DOM 树来确定元素到底是什么样式,为了 CSSOM 的完整性,只有等构建完毕才能进入到下一个阶段,所以就算 DOM 已经构建完了,也得等 CSSOM,然后才能进入下一个阶段

构建渲染树 (Render Tree)

接着 CSSOM 树DOM 树 合并成渲染树,也叫呈现树,渲染树 只包含渲染网页所需的节点,然后用于计算每个可见元素的布局,并输出给绘制流程,将像素渲染到屏幕上

布局 (Layout)

渲染树 同时包含了屏幕上的所有可见内容及其样式信息,有了渲染树,再接着就会进入布局 ( layout ) 阶段了,到目前为止,浏览器计算了哪些节点应该是可见的以及它们的计算样式,但还没有计算它们在设备视口内的确切位置和大小,这就是 布局 ( Layout ) 阶段,也称为 自动重排回流 ( Reflow )

此阶段一般意味着元素的内容、结构、位置或尺寸发生了变化,需要重新计算样式和渲染树

绘制 (Painting)

经由前几步我们知道了哪些节点可见、它们的计算样式以及几何信息,将这些信息及渲染树中的每个节点转换成屏幕上的实际像素,也就是俗称的 绘制栅格化 阶段

合成(Composite)

最后一步合成( composite ),这一步骤浏览器会将各层信息发送给GPU,GPU将各层合成,显示在屏幕上

至此上述的内容就是我理解的一个URL从解析到渲染的生命历程了

干净简洁的概括式回答

PS:这里大体的点我觉得还是要答出来的,可以根据自己的了解进行某些方面的扩展,至少我觉得是这样子的,也是个人理解,欢迎探讨

面试管你好,URL输入到页面渲染,这是一个经典的话题,涉及的知识点也很多,我按照我的个人理解给您简单概括下,有不对的地方还请您指出

首先,客户端浏览器输入URL,由于是域名,应用层DNS开始解析域名

接着,应用层客户端发送一个HTTP请求,把拿到的应用层HTTP请求报文数据分割编号,为了方便安全的传输,传输层会通过TCP三次握手建立TCP/IP链接

建立连接后 网络层 IP协议会查询服务器 MAC地址 也就是物理地址进行数据包的传输

找到对方的 MAC地址 后,将数据发送到 数据链路层传输,到此客户端发送请求阶段结束

接收端的服务器在 数据链路层 接收到数据包,再通过相反的方式将数据一层一层的还原回 应用层

服务器接收到客户端发送的HTTP请求后,会查找客户端请求的资源,并返回响应报文

请求成功后,服务器会返回相应的网页,浏览器接收到响应成功的报文后便开始下载网页,至此,网络通信结束

浏览器拿到网页文件后,首先根据顶部定义的DTD类型进行对应解析方式,网页解析会交给内部GUI渲染线程处理

接着构建DOM树和CSSOM树,过程中,如果遇到节点是 JS ,就会调用 JS引擎 对 JS代码进行解释执行,此时由于 JS引擎GUI渲染线程 互斥,GUI渲染线程 会被挂起,渲染过程停止,如果 JS 代码的运行中对DOM树进行了修改,那么DOM构建要从新开始,然后DOM树和CSSOM树构建为渲染树

然后进入布局阶段,计算渲染树节点在设备视口内的确切位置和大小

再接着将渲染树中每个节点转换成屏幕上的实际像素,也就是绘制阶段

最后的合成阶段浏览器会将各层信息发送给GPU,GPU将各层合成,显示在屏幕上

问:TCP/IP四、五层,OSI七层模型有什么区别?

网络层次可划分为 四层因特网协议栈七层因特网协议栈 ,起初网络分层是标准的七层,也就是我们所说的 OSI 七层模型 ,参考模型是国际标准化组织 ISO 制定的一个用于计算机或通信系统间互联的标准体系,一般称为 OSI参考模型七层模型

所谓的 TCP/IP 四层模型TCP/IP 五层模型 是以 OSI 七层 优化而来,把某些层进行合并了,本质上还是相同的,OSI七层模型 太过细化,有一定的参考意义,但实现起来比较繁琐,相比较而言,TCP/IP模型 比较简洁,具有较强的实际应用价值

TCP/IP 将计算机网络分成了四个层次,一般资料或教程里都是结合 OSI7层模型TCP/IP4层模型,将计算机网络按照5层的模型来讲,5层模型只是为了方便介绍计算机网络原理而设计的,而在实际应用中还是 TCP/IP四层模型

各层对应关系如下

问:DNS解析可优化吗,为什么优化又怎样优化?

是否

可以优化

为什么

用户打开网站的整个流程中,DNS解析是第一环,当用户输入域名并敲回车后,系统调用 DNS客户端,寻找到用户配置或者自动分配的DNS IP,之后就开始整个解析过程,DNS服务器 完成解析到此域名的 数字IP服务器,一般情况下返回给定域名对应的IP地址会花费 20~120毫秒 的时间,而且在这个过程中浏览器什么都不会做直到DNS查询完毕

一旦解析完成,连接建立并保持,也就是顺利的访问以后,网页以后的下载速度就和DNS没关系了,直到下一次重新解析和发起访问请求

很多小型网站,DNS解析时间都接近 0.5s,有些甚至需要 1s 左右才可以解析出结果,一般网站用户的等待时间超过 8s 就会放弃访问,而对于电子商务网站,4s 就是用户忍耐极限,而一般经过优化的小型网站,DNS解析时间都可以控制在 200ms 左右,而带宽在 100M 左右的网站,经过优化,DNS解析时间可以控制在 50~100ms ,所以DNS优化还是很有必要的

怎样

DNS解析优化-善用缓存之TTL

DNS存在着多级缓存,每次找这么多级,很定耗时间,我们要尽量多的让用户直接从运营商的DNS缓存中拿到解析记录,这样就不需要走根域名服务器以下的这些过程,自然就节省了一些时间

购买域名做域名解析时,有一个 TTL 值,它指的是域名解析的生命周期 ( 秒为单位 ),简单来说它表示DNS服务器解析域名时记录在DNS服务器上的缓存时间,这个值的大小设置也是很有学问的,我们要在尽可能快的情况下又要保证当服务器出问题时能够尽快切换

  • 我们自己肯定清楚自己的服务器有没有多台或备份,若无备份,那服务器宕机时只能生抗,所以,TTL 时间对于你来说是越长越好,因为 TTL 短的目的是服务器发生问题时,可以及时切换,这个对于没有备份的网站基本利用不上,所以这时你的 TTL 设置就越长越好,当然了,也不能太长,一般设置 TTL 3600 即可
  • 若有备份或多台服务器,会发生由于服务器宕机需要及时做切换,TTL 时间越短切换越及时,但是 TTL 时间越短,也就意味着运营商DNS经常缓存不住,一般用户,设置为 TTL 600 即可,如果对及时切换,要求特别苛刻的网站,设置 TTL 120 就行

DNS解析优化-负载均衡

在DNS服务器中为同一个主机名配置多个IP地址,在应答DNS查询时,DNS服务器对每个查询将以DNS文件中主机记录的IP地址按顺序返回不同的解析结果,将客户端的访问引导到不同的机器上去,使得不同的客户端访问不同的服务器,从而达到负载均衡的目的,可以根据每台机器的负载量或该机器离用户地理位置的距离入手

就像我们使用CDN厂商做域名解析,它也是利用DNS的重定向技术,DNS服务器会返回一个跟用户最接近的点的IP地址给用户,CDN节点的服务器负责响应用户的请求,提供所需的内容,CDN厂商的域名解析服务器用户量多被访问的次数也多,域名解析服务器的A记录基本上会被各地运营商的DNS一直缓存着,所以服务效果也是最好的

问:TCP/IP协议与UDP协议优缺点及区别?

首先请注意,这题目本身就是一个坑

TCP/IP协议 是一个协议簇,它包括很多协议,UDP协议 只是其中的一个,之所以命名为 TCP/IP协议,是因为TCP和IP协议是两个很重要的协议,就用它两命名了,仅此而已,SO,这个题目是不正确的,正确的问法应该是TCP协议和UDP协议优缺点及区别

你可能会说有面试官这样问吗?别说这抠字眼的题,还真有人因为忽略了这点被安排过 😄

问:TCP协议和UDP协议优缺点及区别?

优缺点

TCP 的优点: 稳定可靠, 这体现在TCP传递数据之前,会有三次握手来建立连接,且在数据传递时,有确认、窗口、重传、拥塞控制机制,在数据传完后,还会断开连接用来节约一些系统资源

TCP的缺点:占用系统资源高,慢且效率低,TCP在传递数据之前,要先建连接,会消耗时间,在数据传递时,确认机制、重传机制、拥塞控制机制等都会消耗大量的时间,而且要在每台设备上维护所有的传输连接,每个连接都会占用系统的CPU、内存等硬件资源

UDP 的优点: 快,UDP是一个无状态的传输协议,所以它在传递数据时非常快

UDP 的缺点: 不可靠,不稳定,因为UDP没有TCP那些可靠的机制,在数据传递时,如果网络质量不好,就会很容易丢包

一般当我们对网络通讯质量有要求的时候,就应该使用TCP,要把整个数据准确无误的传递给对方,比如HTTP、HTTPS、FTP等协议,当对网络通讯质量要求不高的时候,要求网络通讯速度能尽量的快,这时就可以使用UDP,如语音,视频等

区别

  • TCP协议基于连接UDP协议无连接

  • TCP协议面向字节流,简单说TCP把数据看成一连串无结构的字节流而UDP协议面向报文

  • TCP协议传送数据,无差错不丢失不重复,且按序到达,UDP不保证可靠交付和顺序,可能丢包

  • TCP首部开销20字节,UDP的首部开销较小,只有8个字节

  • TCP协议连接只能是点到点的,UDP支持一对一,一对多,多对一和多对多的交互通信

问:简单介绍下TCP三次握手四次挥手?

三次握手 ( 网图侵删 )

PS: 请认真看图并配合下面文字理解

开始时,双端处于 CLOSE (关闭状态),服务端要提供服务,会主动监听某个端口,进入 LISTEN (监听状态)

客户端主动发送连接的SYN包,之后进入 SYN-SENT (同步已发送状态)

服务端在收到客户端发来的SYN包后,回复SYN/ACK包,之后进入 SYN-RCVD (同步收到状态)

客户端收到服务端发来的SYN/ACK包后,确认对方后回复ACK包,并进入 ESTABLISHED (已建立连接状态)

当服务器收到客户端的确认后也进入 ESTABLISHED (已建立连接状态) ,此后双方就可以开始通信了

四次挥手 ( 网图侵删 )

PS: 请认真看图并配合下面文字理解

开始时双端还都处于 ESTABLISHED (已建立连接状态) 并传输数据,某一端可以主动发起 FIN 包准备断开连接,上图为客户端发起 FIN 请求,在发出FIN后,客户端进入 FIN-WAIT-1 (终止等待状态1)

服务端收到 FIN 消息后,回复 ACK 表示知道了,并从ESTABLISHED (已建立连接状态)进入 CLOSED-WAIT (关闭等待状态),开始做一些断开连接前的准备工作

客户端收到之前FIN的回复 ACK 消息后,进入 FIN-WAIT-2 (终止等待状态2),当服务端做好断开前的准备工作后,也会发送一个 FIN/ACK 的消息給客户端,表示我也好了,请求断开连接,并在发送消息后,服务端进入 LAST-ACK (最后确认状态)

客户端在收到 FIN/ACK 消息后,会立即回复 ACK ,表示知道了,并进入 TIME_WAIT ( 时间等待状态),为了稳定和安全考虑,客户端会在 TIME-WAIT ( 时间等待状态) 等待 2MSL ( 最长报文段寿命 ) 的时长,最终进入 CLOSED ( 关闭状态 )

服务端收到客户端回复的 ACK 消息后,直接从 LAST-ACK (最后确认状态) 状态进入 CLOSED ( 关闭状态 )

四次挥手之后,双端都进入 CLOSED ( 关闭状态 ),在此之后,双端正式断开了连接

PS: MSL ( Maximum Segment Lifetime ) 为 最长报文段寿命,它指的是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃,TCP允许不同的实现可以设置不同的 MSL 值

问:为什么建立连接是三次握手,关闭连接确是四次挥手?

建立连接的时候, 服务器在 LISTEN (监听状态) ,收到建立连接请求的 SYN 报文后,把 ACK 和 SYN 放在一个报文里发送给客户端就可以了

而关闭连接时,服务器收到对方的 FIN 报文时,仅代表对方不再发送数据了但是还能接收数据,而自己未必全部数据都发送给对方了,所以自己可以立即关闭,也可以发送一些数据给对方后,再发送 FIN 报文给对方来表示同意现在关闭连接,因此,己方 ACK 和 FIN 一般都会分开发送,从而导致多了一次

问:为什么要三次握手创建链接,最后一次确认有必要吗?

防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误

如果使用两次握手建立连接,假如客户端发送了第一个请求连接并且没有丢失,只是因为在网络结点中滞留的时间太长了,由于 TCP 的客户端迟迟没有收到确认报文,以为服务器没有收到,此时重新向服务器发送这条报文,然后客户端和服务器经过两次握手完成连接,传输数据后关闭连接,此时之前滞留的那一次请求连接,网络通畅了到达了服务器,这个报文本该是失效的,但是,两次握手机制就会让客户端和服务器再次建立连接,会导致不必要的错误和资源的浪费

采用三次握手,就算是那一次失效的报文传送过来了,服务端接受到了那条失效报文并且回复了确认报文,但是客户端不会再次发出确认,由于服务器收不到确认,就会知道客户端并没有请求连接

为什么不用四次握手就更简单了,三次就可以创建安全无误的连接为什么用四次,那不是浪费资源嘛

问:三次握手过程中可以携带数据吗?

第一次、第二次握手不可以携带数据,因为一握二握时还没有建立连接,会让服务器容易受到攻击

而第三次握手,此时客户端已经处于 ESTABLISHED (已建立连接状态) ,对于客户端来说,已经建立起连接了,并且也已经知道服务器的接收、发送能力是正常的了,所以能携带数据也是没问题的

问:四次挥手为什么客户端最后还要等待2MSL?

第一,保证客户端发送的最后一个 ACK 报文能够到达服务器,因为这个 ACK 报文可能丢失,站在服务器的角度看来,我已经发送了 FIN+ACK 报文请求断开了,客户端还没有给我回应,应该是我发送的请求断开报文它没有收到,于是服务器又会重新发送一次,而客户端就能在这个 2MSL 时间段内收到这个重传的报文,接着给出回应报文,并且会重启 2MSL 计时器

第二,比如上面提到了的 已经失效的连接请求报文段 出现在连接中这种状况,客户端发送完最后一个确认报文后,在这个 2MSL 时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失,这样新连接中就不会出现旧连接的请求报文

问:如果已经建立了连接,但客户端突然故障怎么办?

TCP 还设有一个保活计时器,客户端如果出现故障,服务器总不能一直等下去,白白浪费资源啊,服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时

若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,然后每隔75秒就会再发送一次,10次探测报文后仍然没反应的话,服务器就认为客户端出了故障,接着就关闭连接

问:HTTP 的请求方法?

HTTP1.0 定义了三种请求方法: GET, POST 和 HEAD方法

HTTP1.1 新增了六种请求方法:OPTIONS、PUT、PATCH、DELETE、TRACE 和 CONNECT 方法

序号 方法 描述
1 GET 请求指定的页面信息,并返回实体主体
2 HEAD 类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头
3 POST 向指定资源提交数据进行处理请求 ( 例如提交表单或者上传文件 ),数据被包含在请求体中,POST 请求可能会导致新的资源的建立和/或已有资源的修改
4 PUT 从客户端向服务器传送的数据取代指定的文档的内容
5 DELETE 请求服务器删除指定的页面
6 CONNECT HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器
7 OPTIONS 允许客户端查看服务器的性能
8 TRACE 回显服务器收到的请求,主要用于测试或诊断
9 PATCH 是对 PUT 方法的补充,用来对已知资源进行局部更新

问:HTTP 状态码分别代表什么?

状态码有五类分别代表

  • 1xx: 协议处理中状态,还需后续操作
  • 2xx: 成功状态
  • 3xx: 重定向状态,资源位置发生变动,需要重新请求
  • 4xx: 请求报文有误
  • 5xx: 服务器端错误

详细状态码就不啰嗦了,直接 copy 菜鸟教程了一份,看一看吧,心中有个印象

状态码 英文名称 描述
100 Continue 继续。客户端应继续其请求
101 Switching Protocols 切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议,例如,切换到HTTP的新版本协议
200 OK 请求成功。一般用于GET与POST请求
201 Created 已创建。成功请求并创建了新的资源
202 Accepted 已接受。已经接受请求,但未处理完成
203 Non-Authoritative Information 非授权信息。请求成功。但返回的meta信息不在原始的服务器,而是一个副本
204 No Content 无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档
205 Reset Content 重置内容。服务器处理成功,用户终端(例如:浏览器)应重置文档视图。可通过此返回码清除浏览器的表单域
206 Partial Content 部分内容。服务器成功处理了部分GET请求
300 Multiple Choices 多种选择。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于用户终端(例如:浏览器)选择
301 Moved Permanently 永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替
302 Found 临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI
303 See Other 查看其它地址。与301类似。使用GET和POST请求查看
304 Not Modified 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源
305 Use Proxy 使用代理。所请求的资源必须通过代理访问
306 Unused 已经被废弃的HTTP状态码
307 Temporary Redirect 临时重定向。与302类似。使用GET请求重定向
400 Bad Request 客户端请求的语法错误,服务器无法理解
401 Unauthorized 请求要求用户的身份认证
402 Payment Required 保留,将来使用
403 Forbidden 服务器理解请求客户端的请求,但是拒绝执行此请求
404 Not Found 服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面
405 Method Not Allowed 客户端请求中的方法被禁止
406 Not Acceptable 服务器无法根据客户端请求的内容特性完成请求
407 Proxy Authentication Required 请求要求代理的身份认证,与401类似,但请求者应当使用代理进行授权
408 Request Time-out 服务器等待客户端发送的请求时间过长,超时
409 Conflict 服务器完成客户端的 PUT 请求时可能返回此代码,服务器处理请求时发生了冲突
410 Gone 客户端请求的资源已经不存在。410不同于404,如果资源以前有现在被永久删除了可使用410代码,网站设计人员可通过301代码指定资源的新位置
411 Length Required 服务器无法处理客户端发送的不带Content-Length的请求信息
412 Precondition Failed 客户端请求信息的先决条件错误
413 Request Entity Too Large 由于请求的实体过大,服务器无法处理,因此拒绝请求。为防止客户端的连续请求,服务器可能会关闭连接。如果只是服务器暂时无法处理,则会包含一个Retry-After的响应信息
414 Request-URI Too Large 请求的URI过长(URI通常为网址),服务器无法处理
415 Unsupported Media Type 服务器无法处理请求附带的媒体格式
416 Requested range not satisfiable 客户端请求的范围无效
417 Expectation Failed 服务器无法满足Expect的请求头信息
500 Internal Server Error 服务器内部错误,无法完成请求
501 Not Implemented 服务器不支持请求的功能,无法完成请求
502 Bad Gateway 作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应
503 Service Unavailable 由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中
504 Gateway Time-out 充当网关或代理的服务器,未及时从远端服务器获取请求
505 HTTP Version not supported 服务器不支持请求的HTTP协议的版本,无法完成处理

问:HTTP与HTTPS的区别?

HTTP协议传输的数据都是未加密的,也就是明文的,所以使用HTTP协议传输隐私信息非常不安全,为了保证这些隐私数据能加密传输,于是网景公司设计了 SSL(Secure Sockets Layer) 协议用于对HTTP协议传输的数据进行加密,从而就诞生了HTTPS

简单来说,HTTPS协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,要比 HTTP 协议安全,更多HTTP和HTTPS内容请自行百度,这里就不长篇大论了

那么简单总结下有区别

  • HTTPS协议需要到 CA 申请证书,一般免费证书较少,因而需要一定费用

  • HTTP是超文本传输协议,信息是明文传输,HTTPS 则是具有安全性的 SSL 加密传输协议

  • HTTP和HTTPS使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443

  • HTTP的连接很简单,是无状态的,HTTPS协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,比HTTP协议安全

问:什么是简单请求和非简单请求?

CORS(cross-origin resource sharing),跨源资源共享,就是广大前端同学所说的跨域,想必大家都了解,不了解这也不做介绍了,不了解可以看 HTTP访问控制(CORS)- MDN传送门 😄

CORS中把请求定义为了两类

  • 简单请求
  • 非简单请求

那么什么是简单请求什么是非简单请求呢?其实也很简单,我们只需要知道什么是简单请求,其余的就都是非简单的了,而简单请求需要满足的条件是

  • 请求方式只能是GET、POST、HEAD三种
  • HTTP头部信息不超过一下几种字段
    • 无自定义头部字段
    • Accept、Accept-Language、Content-Language、Last-Event-ID
    • Content-Type只有三个值 application/x-www-form-urlencoded、multipart/form-data、text/plain

简单请求需要满足上面的条件,其实平常也就是传统的表单请求了,看了上面的简单请求条件,那么非简单请求是不是就呼之欲出了呢,比如下面这些只要满足一个就是非简单请求

  • 请求方式是PUT、DELETE

  • 自定义头部字段

  • 发送JSON格式数据等等

非简单请求的 CORS 请求,会在正式通信之前,增加一次 HTTP 查询请求,请求方式为 OPTIONS,称为 预检请求 (preflight)

浏览器会先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些 HTTP 方法和头信息字段,得到肯定答复,浏览器才会发出正式的 XMLHttpRequest 请求,否则就会报错,这是为了防止这些新增的请求,对传统的没有 CORS 支持的服务器形成压力,给服务器一个提前拒绝的机会,防止服务器收到大量 DELETE 和 PUT请求,这些传统的表单不可能跨域发出的请求

问:CSS 资源加载会阻塞渲染怎样优化?

优化DOM树,DOM尽可能的小

CSS尽量用 idclass 少直接用标签,因为标签节点样式是可以继承的,所以在构建的过程中浏览器得递归 DOM 树来确定元素到底是什么样式

对于首屏渲染需要用到的CSS代码加入Inline CSS ( 内联样式 )

对于首屏渲染不需要用到的CSS,可以使用文件形式并在页面内容渲染完成后再加载

问:什么是回流和重绘以及区别?

要知道,生成DOM树时是包括 display:none 的节点的,DOM树和CSSOM树的基础上根据节点的集合属性 margin/padding/width/height等 生成渲染树 ( render ) ,渲染树不包括 display:none 的节点和 head 等节点,但是包括 visibility:hidden 的节点

当渲染树节点因为大小边距等问题发生改变而需要重建的过程,叫做 回流 (Reflow)

元素发生的改变只是影响了元素的一些外观之类的时候 ( 例如,背景色,边框颜色,文字颜色等 ),此时只需要应用新样式绘制这个元素就可以了,称之为 重绘 (Repaint)

回流必将引起重绘,而重绘不一定会引起回流,很明显 回流 代价较大

问:什么会引起回流?

  • 页面渲染初始化

  • DOM结构改变,比如删除了某个节点

  • render树变化,比如减少了 padding ( 内边距 )

  • 窗口 resize 事件触发时

  • 某些 JS 属性,引发回流,很多浏览器会对回流做优化,等到数量足够时做一次批处理回流, 但除了 render树 的直接变化,当获取一些属性时,浏览器为了获得正确的值也会触发回流,这样使得浏览器优化无效

    • offset ( Top/Left/Width/Height )
    • scroll ( Top/Left/Width/Height )
    • cilent ( Top/Left/Width/Height )
    • width, height
    • 调用了 getComputedStyle() 或者IE的 currentStyle

问:如何减少和避免回流重绘?

减少逐项更改样式,最好一次性更改 style,或者将样式定义为 class 并一次性更新

避免循环操作DOM,让DOM离线后再修改

  • 创建一个 documentFragment ,在它上面应用所有DOM操作,最后再把它添加到 window.document
  • 先把DOM节点 display:none ( 会触发一次 reflow),然后做修改后,再把它显示出来
  • 克隆一个DOM节点在内存里,修改之后,与在线的节点相替换

避免多次读取offset等属性,无法避免则将它们缓存到变量

将复杂的元素绝对定位或固定定位,使得它脱离文档流,否则回流代价会很高

改变字体大小也会引发回流,所以尽可能减少这种操作

table布局,一个小改动会造成整个table的重新布局,所以,少用为好

问:你了解普通图层和复合图层吗?

浏览器渲染的图层一般包含两大类:普通图层 以及 复合图层

普通文档流可以理解为一个复合图层,我们叫它默认复合层,因为里面不管添加多少元素,其实都是在同一个复合图层中,absolute 布局、 fixed 也一样,虽然可以脱离普通文档流,但它仍然属于 默认复合层

复合图层,可以独立于普通文档流中,改动后可以避免整个页面重绘,从而提升性能,但也不能大量使用复合图层,否则由于资源消耗过度,页面反而会变的更卡,因小失大

GPU中,各个复合图层是单独绘制的,所以也互不影响,通过 硬件加速 的方式,会声明一个 新的复合图层 ,它会单独分配资源,当然也会脱离普通文档流,这样一来,不管这个复合图层中怎么变化,也不会影响 默认复合层 里的回流重绘

PS: 硬件加速技术是指使用 GPU 的硬件能力来帮助渲染网页

问:浏览器页面渲染优化?

  • HTML文档结构层次尽量少,最好不深于六层

  • JS 脚本尽量后放

  • 样式结构层次尽量简单

  • 少量首屏样式使用内联方式放在标签内

  • 在脚本中尽量减少DOM操作,尽量访问离线DOM样式信息,避免过度触发回流

  • 减少通过 JS 代码修改元素样式,尽量使用修改 class 名方式操作样式或动画

  • 尽量减少浏览器重排和重绘的一些情况发生

  • 2020年了!就不要使用 table 布局了

  • CSS 动画中尽量只使用 transformopacity ,不会发生重排和重绘

  • 隐藏在屏幕外,或在页面滚动时,尽量停止动画

  • 尽可能只使用 CSS 做动画,CSS动画肯定比 JS 动画要好很多

  • 避免浏览器的隐式合成

  • 改变复合层的尺寸

最后

对您有帮助的话,动动小手,点个赞鼓励下吧,当然,个人理解,本文因为比较忙,写的时间较长,断断续续的写,所以可能有些地方衔接的不好,不太通顺或者有不正的地方,欢迎指出,不胜感激

哦,还有,可以加个好友加下群一起交流噻,公众号【不正经的前端】也欢迎关注呦 😄