
此文是一道面试题,又不仅仅是一道面试题
从输入 URL 到页面渲染发生了什么?比如在浏览器输入了 www.qq.com 后浏览器是怎么把最终的页面呈现,这是一个非常经典的面试题,不管是大公司还是小公司甚至前端或后端的面试中命中率都极高,因为涉及到的知识点和可挖掘的地方比较多,而且这中间几乎每一步都是可以优化的
既然大家刷到了这篇帖子,希望大家花点时间耐心看完,不会让你失望的,此文从网络五层模型详解析及浏览器页面渲染机制等多方面来认识URL从输入到页面渲染的整个过程,内容还是满充实的
写着写着发现有点长,就分成三篇了 😄
前两篇文章都是帮助大家理解整个过程,所以并没有直接给出答案,而是给大家梳理解释一些相关琐碎的知识,目的不是答题,而是彻底理解此间流程,大家只要认真看到最后一篇就可以骄傲的回答这道题了,自己心中给自己一个答案,再看最后一篇我个人通过这些知识总结的答案 ( 如果你的总结更加充实/细致,请在评论区分享出来,我们一起查漏补缺 ) ,先看后思考,再总结相互讨论,效果最佳
URL从输入到页面渲染这整个过程可以分为 网络通信 和 页面渲染 两个方面,一般后端程序猿回答这个问题侧重网络通信就行了,但是前端页面渲染也得了解,总之回答的越详细分值越高
那么开始吧,这篇文章我们先来看网络通信方面,可能前端同学大家对网络方面的认知应该没有后端同学强,其实这道面试题最能突出自己的也是网络方面,因为它涉及到了很多网络通信原理的知识,所以这块咱们慢慢梳理
不晓得大家知不知道网络分层,网络其实有很多层,层与层之间又有好多协议存在,还有各种各样的数据包,这玩意干巴巴的,很没意思,这么多层太麻烦了,为什么有这么多层呢?为什么不直接一层呢?
起初计算机与计算机之间的通信只需要一根线就可以完成通信,但是世界那么大,那么多计算机,距离太远了,而且这线还老容易被无良的人偷偷剪断
后来就出来了无线网,虽然其中网关、路由之间也需要连线,但不是让每台计算机两两连接,而是一个区域为单位计算机相互连接通信
后来发现计算机之间的连线只能传送0/1信号,另一台计算并不知道那么多0/1代表什么,就像 010101010101111000111011010 你知道这一大串是什么意思吗,计算机也不知道,不同厂商生产的计算机连线实现通信也是很麻烦的,干脆定义一套规则吧,不管是哪个牌子的计算机,都必须遵守这套规则,这套规则就是我们经常说的 网络协议
哦哦,是在说 网络分层 ,不是讲 网络协议 ,继续继续,接着我们上面的话题,问题来了,计算机之间通过连线传送0/1信号的问题虽然规定了通信规则,但是除了像0/1这种无意义的信号之外,网络中还存在着其他各种各样的问题
如果各种问题都写成一套协议来规定双方通信的规则,但是万一其中哪些规则通信中出现问题,影响到了其他规则,最常见的就是数据包,一个数据包中如果包含各种各样的协议,呀呀呀
如果我们对网络进行分层,每一层负责一项具体的工作,然后把数据传送到下一层,那么往来通信和网络互联这一复杂的问题是不是就变得较为简单化了呢
可能大家没有太明白,没关系,接着看
既然要分层,那么分为几层才好呢?
目前的网络层次可划分为 四层因特网协议栈 和 七层因特网协议栈 ,其实起初网络分层是标准的七层,也就是我们所说的 OSI 七层模型 ,参考模型是国际标准化组织 ISO 制定的一个用于计算机或通信系统间互联的标准体系,一般称为 OSI参考模型 或 七层模型
可能对网络有些了解的同学知道还有 TCP/IP 四层模型 和 TCP/IP 五层模型 ,这又是怎么出来的呢?
其实所谓的 TCP/IP 四层模型 和 TCP/IP 五层模型 是以 OSI 七层 优化而来,把某些层进行合并了,本质上还是相同的,OSI七层模型 太过细化,有一定的参考意义,但实现起来比较繁琐,相比较而言,TCP/IP模型 比较简洁,具有较强的实际应用价值
我们来看一个模型的图片 ( 网图侵删 )

TCP/IP 将计算机网络分成了四个层次,一般资料或教程里都是结合 OSI7层模型 和 TCP/IP4层模型,将计算机网络按照5层的模型来讲,5层模型只是为了方便介绍计算机网络原理而设计的,而在实际应用中还是 TCP/IP四层模型 ,这点大家要明白
这里我们同样用五层来解释,比较好理解些,当然,这里只能让大家脑海里有一个具体的网络分层结构的认知,作为面试回答了解这些足够,而后推荐大家继续深入,可以看相关的书籍和资料,此文也能够起到一个引导的作用
「PS:」 作为一个前端或者是后端,我们都是软件开发,所以侧重点放在网络层以上就可以了,物理层和数据链路层都是硬件相关的,所以这两个层下面不会过多叙述,了解即可
物理层,顾名思义,通过物理手段 ( 网线,光纤,无线 ) 将设备连接在一起,传输0/1电信号 ( 也叫比特流 ) ,就像我们上边讲到的计算机之间的物理连线
主要用来传输0/1信号,因为0/1信号没有任何的现实意义,所以用另一层用来规定不同0/1组合的意义
还是上面说的,010101010101111000111011010 ,像这么一串数据计算机并不知道是什么意思
下层的物理层不能规定不同0/1组合的信号代表什么意义,所以在数据链路层规定了一套协议,专门给0/1信号进行分组,规定不同的组代表的是什么意思,从而让双方计算机都能够进行识别,这个协议就是我们常说的 以太网协议
以太网协议规定一组电信号构成一个数据包,我们把这个数据包称为 帧 ,每一个帧由 标头 和 数据 两部分组成
帧的大小一般为 64 - 1518 个字节 较大的数据则需要分成多个桢
标头 Head ,18个字节组成,标头中包含这个 桢 是由谁发送、发送给谁这些信息,所以标头主要是一些说明数据 例如发送者/接受者等信息
数据 Data ,46-1500个字节组成,里面主要是发送者想给接收者的内容
把一台计算机的数据通过物理层和数据链路层发送给另外一台计算机,怎么标识对方以及怎么知道对方的地址呢?唯一标识 MAC地址 出现了
进入网络的每一台计算机,都会有网卡接口,每一个网卡都会有一个唯一的地址,就是所谓的 MAC地址 ,它就是网络中每台计算机设备的唯一标识,是一串由48个字节组成的十六进制数,每台计算机在厂商生产出来的时候就标识好了,所以我们用 MAC地址 来标识对方
再来看一个图 ( 网图侵删 )

如上图所示,如计算机A知道了计算机B的MAC地址,然后计算机A想要给计算机B传送数据,虽然计算机A知道了计算机B的MAC地址,可是A要怎么给B传送数据呢?
计算机A不仅连着计算机B,而且计算机A也连接着计算机C和D,虽然计算机A知道计算机B的MAC地址,但是却不知道B是在哪一路上,所以为了解决这个问题,广播 这个概念就出现了
在同一子网络,就是我们常说的局域网中,计算机通过广播来通信,即向同子网中全部计算机发送数据包,其它计算机根据数据包中接收者的 MAC地址 来判断是否接收数据包
通俗来讲,就是A会同时给B/C/D发送数据包,这个数据包中会包含着接收者的 MAC地址 信息,当B/C/D接收到了数据包,会取出数据包中的 MAC地址 与自身的 MAC地址 对比,如相同就接收这个数据包,否则就丢弃这个数据包 ( 丢包 ),这种方式我们称之为 广播
就像,你和女友在人群中走散了,你大喊一声她的名字,听到的人会自己匹配,是自己就会理会,不是自己就当你是傻子不理你
那么到了目前,我们知道了计算机之间的标示和如何通信,但是还有一个问题,要怎么知道对方的 MAC地址 呢 ?这又牵出了 ARP协议 ,通过 ARP协议 来得知对方的 MAC地址 ,这个协议是网络层的一个协议,所以我们暂且搁置,先接着往下看
看了物理层和数据链路层的作用,可能大家会觉得好像已经可以完成正常通信了,那么网络层又是做什么的呢?
其实我们所处的网络,是由无数个子网络 ( 局域网 ) 构成的,广播的时候,也只有同一个子网里的计算机能够收到,如果没有子网这种东西,计算机A通过广播的方式发一个数据包给计算机B,那么全世界所有的计算机都能收到这个数据包,然后进行对比再舍弃,那么多台计算机后果可想而知,子网也因此而产生
那么问题又来了,我们要怎么区分 Mac地址 是属于同一个子网的呢?假如是同一个子网,我们就用广播的形式把数据传送给对方,如果不是同一个子网的,我们就会把数据发给网关,让网关进行转发
怎么判断两台计算机是否在同一个子网中呢,这就是网络层干的事情,为了解决这个问题,就有了 IP协议 的概念
IP协议所定义的地址,就是我们常说的 IP地址 ,IP协议 有两个版本,ipv4 / ipv6,目前用的最多的还是ipv4,这个地址由32位的二进制数组成,我们一般把它分成4段的十进制表示,地址范围在 0.0.0.0 ~ 255.255.255.255 ,这个我们应该都很常见
每一台想要联网的计算机都会有一个 IP地址 ,这个 IP地址 分为两部分,前面一部分代表网络,后面一部分代表主机,但是网络部分和主机部分所占用的二进制位数是不固定的
假如两台计算机的网络部分是一模一样的,我们就说这两台计算机是属于同一个子网 ( 局域网 ) 中,例如 192.168.17.1 和 192.168.17.2 , 假如这两个 IP地址 的网络部分为 24 位,主机部分为 8 位,那么他们的网络部分都为 192.168.43 , 所以我们说这两台计算机处于同一个子网中
问题又随之而来了,给我们两个 IP地址 ,鬼知道网络部分占几位,主机部分又占几位呢?
这就又引出了我们另一个关键词 子网掩码
子网掩码 和 IP地址 一样也是32位二进制数,但是它的网络部分规定全部为1,主机部分规定全部为0,也就是说假如上面那两个 IP地址 的网络部分为24位,主机部分为8位的话,那他们的子网掩码为
11111111.11111111.11111111.00000000 ,也就是 255.255.255.0
有了子网掩码,怎么来判断 IP地址 是否处于同一个子网中呢?
显然,知道了子网掩码,相当于我们知道了网络部分是几位,主机部分是几位,我们只需要把 IP地址 与他的子网掩码做一个 ( and ) 运算,然后把各自的结果进行比较就行了,如果比较的结果相同,则代表的是同一子网,否则不是同一子网
也就是说有了两台计算机的 IP地址 和 子网掩码 ,我们就可以判断他们是否处在同一子网当中了
假设他们处在同一子网当中,计算机A要和计算机B发送数据时,我们通过是 ARP协议 来得到计算机的 MAC地址
ARP协议 也是通过广播的形式,给同一个子网中每个电脑发送一个数据包,这个数据包会包含接收者的 IP地址,对方收到这个数据之后,会取出 IP地址 与自身的对比,相同则会把自己的 MAC地址 回复给对方,否则就丢弃这个数据包,这样计算机A就知道计算机B的 MAC地址 了
可能大家会问,知道了 MAC地址 后,发送数据是通过广播的形式发送,询问对方的 MAC地址 也是通过广播的形式来发送,那其他计算机怎么知道你是要传输数据还是询问 MAC地址 呢?
其实在询问 MAC地址 的数据包里,在对方的 MAC地址 这儿填的是一个特殊的 MAC地址 ,其他计算机看到这个特殊的 MAC地址 后,就知道广播是在询问了
如果两台计算机的 IP 不是处于同一个子网之中,这个时候我们就会把数据包发送给网关,然后让网关帮我们进行转发
通过 物理层 / 数据链路层 以及 网络层 的互相协调,我们成功的把数据从计算机A传到了计算机B,可是计算机B里面有各式各样的应用程序,计算机是如何知道这个数据是发给哪个应用程序的呢?
这个时候,端口 就上场了,当计算机A传输给计算机B的时候,还得指定一个端口,以供特定的应用程序来接收处理,作为程序员的我们对端口就更熟悉了,端口范围:0~65535,其中前1023个端口被系统占用
那么也就是说,传输层的功能就是建立端口到端口的通信,而相比之下网络层的功能是建立主机到主机的通信
有了 IP 和 端口 ,我们才能准确通信,我们输入的IP有些并没有指定端口号,其实是有些传输协议,设定了一些默认端口,例如 HTTP 默认是80,HTTPS 默认443,这些端口信息也会包含在数据包里面
传输层最常见了两大协议就是 TCP协议 和 UDP协议
UDP协议 全称是用户数据报协议,是一种无连接的协议,与TCP协议一样用于处理数据包
UDP数据包分 标头 (8个字节) 和 数据 (加标头不超过65535个字节), UDP数据包放在IP数据包的 数据 中,标头主要包括发出端口和接收端口
UDP有不提供数据包分组、组装和不能对数据包进行排序的缺点,也就是说,当报文发送之后,是无法得知其是否安全完整到达的
当一台计算机想要与另一台计算机通讯时,两台计算机之间的通信需要畅通且可靠,这样才能保证正确收发数据
如果数据丢失或乱序,都不是你希望得到的结果,于是就用到了 TCP
TCP协议 全称是传输控制协议是一种面向连接的、可靠的、基于字节流的传输层通信协议,TCP 是面向连接的、可靠的流协议,什么是流?流就是指不间断的数据结构,可以把它想象成排水管中的水流
TCP三次握手建立连接,四次挥手断开连接又是一个话题,接下来我们就简单说一下
三次握手建立链接,为方便理解,仿一次电面
接着,小李和面试官开始愉快的侃起了大山
根据上面的内容,我们再来看下图 (网图侵删)

按正规流程来说建立连接的三次握手如下
SYN-SENT 状态SYN-RECEIVED 状态ESTABLISHED 状态,服务端收到这个应答后也进入 ESTABLISHED 状态,此时连接建立成功可能大家会有疑惑,为什么 TCP 建立连接需要三次握手,而不是两次?
其实这是为了防止出现失效的连接请求报文段被服务端接收的情况,从而产生错误
四次挥手断开链接,接着仿电面 😄
再看正经的过程图 (网图侵删)

TCP是双向的,所以在断开连接时两端都需要发送 FIN 和 ACK
ACK 包,并进入 CLOSE_WAIT 状态,此时表明 A 到 B 的连接已经释放,不再接收 A 发的数据了,但是因为 TCP 连接是双向的,所以 B 仍旧可以发送数据给 ALAST-ACK 状态TIME-WAIT 状态,该状态会持续 2MSL(最大段生存期,指报文段在网络中生存的时间,超时会被抛弃)时间,若该时间段内没有 B 的重发请求的话,就进入 CLOSED 状态,当 B 收到确认应答后,也便进入 CLOSED 状态客户端需要保证最后一次发送的 ACK 报文到服务器,如果服务器未收到,可以请求客户端重发,这样客户端还有时间再发,重启 2MSL 计时
其实浏览器对同一域名下并发的 TCP 连接是有限制的(2-10个不等)
而且在 HTTP1.0 中往往一个资源下载就需要对应一个 TCP/IP 请求
三次握手,这样能建立可靠的连接,为数据的可靠传输打下了基础到了现在,大家应该对UDP和TCP都有些了解了,我们直接对比其作用再进行总结
对比 | UDP | TCP |
|---|---|---|
是否连接 | 无连接 | 面向连接 |
是否可靠 | 不可靠传输,不使用流量控制和拥塞控制 | 可靠传输,使用流量控制和拥塞控制 |
连接个数 | 支持一对一,一对多,多对一和多对多通信 | 只能一对一通信 |
传输方式 | 面向报文 | 面向字节流 |
首部开销 | 首部开销小,仅8字节 | 首部最小20字节,最大60字节 |
适用场景 | 适用于实时应用 ( IP电话、视频会议、直播等 ) | 适用于要求可靠传输的应用,例如文件传输 |
TCP 我们就简单说到这里,接下来我们接着来看应用层
应用层是最接触用户的,上面几层我们收到了传输层收到的数据,TCP/UDP协议可以传递各种程序的数据包,就像邮箱/网页/FTP等等,所以就需要不同的协议来规定数据的格式,收到后才能渲染解读,应用层就是由这些协议构成,它的数据包放在UDP包/TCP包的 数据 中
我们遨游网络时经常用到的 HTTP 协议、文件传输用的 FTP 协议、电子邮件发送的 SMTP、域名解析的 DNS 协议、远程登录的 Telnet 协议等等都是属于应用层的
还有Socket,它是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作封装成几个简单的接口供应用层调用,从而实现进程在网络中的通信
上面我们已经基本了解到了计算机的一些通信基础,可以说到目前为止从一个IP到通信结束都已经知道了,但是我们输入的是域名不是IP,那么它是怎么变成IP通信的呢?这就要详细说说 DNS 了
Domain Name System 简写 DNS ,翻译过来就是域名系统的意思,它是一种组织成域层次结构的计算机和网络服务命名系统,用于 TCP/IP 网络,作为将域名和IP地址相互映射的一个分布式数据库,它所提供的服务是用来将 主机名 和 域名 转换为 IP地址 的工作
简单来说,IP地址 就像门牌号一样,我们在输入域名访问网站时,数据服务器是不认识你这个域名的,它只认识IP,你的域名会通过 DNS服务器 解析成IP值,通过这个门牌号 (IP值) 向数据服务器查找你的网站数据并给你返回到浏览器上
上面我们说,网络通讯大部分是基于TCP/IP的,而TCP/IP是基于IP地址的,所以计算机在网络上进行通讯时只能识别如 252.94.131.12 之类的IP地址,而不能认识域名
我们没办法记住10个以上IP地址的网站 ( 你要说记性好那俺就乖乖闭嘴了😄 ),一般我们访问网站时,更多的是在浏览器地址栏中输入域名,就能看到所需要的页面,这是因为有一个叫 DNS服务器 的计算机自动把我们的域名 翻译 成了相应的IP地址,然后通过 IP地址 返回所对应的网页
先来简单介绍下域名结构,有些前端同学可能不太了解,域名是在 Internet 上用于解决IP地址的一种方法,一个完整的域名由2个或2个以上的部分组成,各部分之间用英文的句号 . 来分隔
拿 www.qq.com. 来说,等等,是不是多打了一个点,当然不是多打,这个最后的 . 代表的是根域名,默认情况下所有的网址的最后一位都是 .,只不过为了方便用户,通常都会省略,浏览器在 DNS解析 时会自动加上的,com是顶级域名,qq 是二级域名,www 是三级域名,如果 www 前还有,那就四级等等
那么我们在解析时的顺序就是
. -> .com -> qq.com -> www.qq.comDNS是应用层协议,用于将用户提供的主机名解析为ip地址,它的获取流程大致分为下面这五步
http://www.qq.com假如我们要访问 www.qq.com ,那么要经历什么呢,先来看一张图 ( 网图侵删 )

先简单的瞄一眼这张图,看不懂也没关系,结合文字再看
上图主要分为三个段
互联网服务提供商服务器/根域名服务器/顶级域名服务器/主域名服务器DNS获取流程有很多步骤,这个过程中存在多个请求,如果每次都经过这么多步骤,那就太耗时间了,所以DNS有多级缓存的概念,接下来我们来简单描述下这个过程
www.qq.com 时,浏览器首先会在自己缓存中查找是否有该域名对应的IP地址Hosts 文件DNS缓存是否有该域名对应IP.com ) 服务器IP告诉本地DNS服务器qq.com )服务器的IP地址告诉本地DNS服务器www.qq.com )进行查找,并重复该步骤直至找到正确纪录DNS客户机可通过从以前查询获得的缓存信息就地应答查询,DNS服务器可使用其自身的资源记录信息缓存来应答查询,也可代表请求客户机来查询或联系其他DNS 服务器,以完全解析该名称,并随后将应答返回至客户机,这个过程称为 递归查询
客户机自己尝试联系其他的 DNS服务器来解析名称,如果客户机这么做,它会使用基于服务器应答的独立和附加的查询,该过程称作迭代,即DNS服务器之间的交互查询就是 迭代查询
这就是DNS的整个过程了,是这道面试题的第一步,面试官可能还会问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存在着多级缓存,每次找这么多级,肯定耗时间,我们要尽量多的让用户直接从运营商的DNS缓存中拿到解析记录,这样就不需要走根域名服务器以下的这些过程,自然就节省了一些时间
我们购买域名做域名解析时,有一个 TTL 值 ( 如下图阿里云域名解析中所示 )

它指的是域名解析的生命周期 ( 秒为单位 ),简单来说它表示DNS服务器解析域名时记录在DNS服务器上的缓存时间,这个值的大小设置也是很有学问的,我们要在尽可能快的情况下又要保证当服务器出问题时能够尽快切换
TTL 时间对于你来说是越长越好,因为 TTL 短的目的是服务器发生问题时,可以及时切换,这个对于没有备份的网站基本利用不上,所以这时你的 TTL 设置就越长越好,当然了,也不能太长,一般设置 TTL 3600 即可TTL 时间越短切换越及时,但是 TTL 时间越短,也就意味着运营商DNS经常缓存不住,一般用户,设置为 TTL 600 即可,如果对及时切换,要求特别苛刻的网站,设置 TTL 120 就行在DNS服务器中为同一个主机名配置多个IP地址,在应答DNS查询时,DNS服务器对每个查询将以DNS文件中主机记录的IP地址按顺序返回不同的解析结果,将客户端的访问引导到不同的机器上去,使得不同的客户端访问不同的服务器,从而达到负载均衡的目的,可以根据每台机器的负载量或该机器离用户地理位置的距离入手
就像我们使用CDN厂商做域名解析,它也是利用DNS的重定向技术,DNS服务器会返回一个跟用户最接近的点的IP地址给用户,CDN节点的服务器负责响应用户的请求,提供所需的内容,CDN厂商的域名解析服务器用户量多被访问的次数也多,域名解析服务器的A记录基本上会被各地运营商的DNS一直缓存着,所以服务效果也是最好的
说完DNS,本来还想写段HTTP和HTTPS,这块也能说好久,但是后来又感觉写在这有些不太合适,那就下次有机会单独写吧
网络通信篇到此结束,虽然此文写了上万字,但只能说整合了内容讲了个大概,怎么说呢,网络通信相关的一些知识都有提到,但并未深入,所以面试前临阵磨枪或查漏补缺可以,不要妄想通过看此文或者某一篇帖子就认为自己懂了网络通信,TCP/IP/DNS/HTTP/HTTPS这些内容随便挑出来一个都可以长篇大论
当然,和大多数帖子一样,此文庞观的为大家梳理了一下网络通信的内容,并用通俗易懂的语气为大家描述,这也是为了大多数非科班出身的小伙伴,有错误的地方望海涵也望提出
如果大家想进一步了解网络通信,也可以此文为引子,深入看一些相关知识,第三文总结也为大家整理出来了网络和浏览器方面知识的思维导图,哪里不会自己去查资料找答案即可
下一文「一道面试题」输入URL到渲染全面梳理中-页面渲染篇,待续哦。。