目录
这是一道经典的面试题,能比较全面地考察应聘者知识的掌握程度,其中涉及到了网络、操作系统等一系列的知识。但遗憾的是大多数人只能回答其中部分零散的知识点,并不能将这些知识点串联成线,无法系统而又全面地回答这个问题。
解析URL
分析你输入的是一个地址,还是想在直接使用搜索引擎搜索
- 如果是搜索内容,地址栏会使用浏览器默认的搜索引擎,来合成新的带搜索关键字的URL。
- 如果判断输入内容符合URL规则,比如输入的是 time.geekbang.org,那么地址栏会根据规则,把这段内容加上协议,合成为完整的URL,如 https://weixin.qq.com/。
当用户输入关键字并键入回车之后,这意味着当前页面即将要被替换成新的页面,不过在这个流程继续之前,浏览器还给了当前页面一次执行beforeunload事件的机会,beforeunload事件允许页面在退出之前执行一些数据清理操作,还可以询问用户是否要离开当前页面,比如当前页面可能有未提交完成的表单等情况,因此用户可以通过beforeunload事件来取消导航,让浏览器不再执行任何后续工作。
DNS解析出IP地址
DNS( Domain Name System)是“域名系统”的英文缩写,是一种组织成域层次结构的计算机和网络服务命名系统,它用于TCP/IP网络,它所提供的服务是用来将主机名和域名转换为IP地址的工作。DNS就是这样的一位“翻译官”,用来把我们输入的域名解析为ip
域名有三个部分,以weixin.qq.com
为例:com
是顶级域名, qq
是二级域名, weixin
是三级域名(通常被称为子域名)
- 浏览器缓存
当用户通过浏览器访问某域名时,浏览器首先会在自己的缓存中查找是否有该域名对应的IP地址(若曾经访问过该域名且没有清空缓存便存在);
- 系统缓存
当浏览器缓存中无域名对应IP则会自动检查用户计算机系统Hosts文件DNS缓存是否有该域名对应IP;
- 路由器缓存
当浏览器及系统缓存中均无域名对应IP则进入路由器缓存中检查,以上三步均为客服端的DNS缓存;
- ISP(互联网服务提供商)DNS缓存
当在用户客服端查找不到域名对应IP地址,则将进入ISP DNS缓存中进行查询。比如你用的是电信的网络,则会进入电信的DNS缓存服务器中进行查找;
- 根域名服务器
当以上均未完成,则进入根服务器进行查询。全球仅有13台根域名服务器,1个主根域名服务器,其余12为辅根域名服务器。根域名收到请求后会查看区域文件记录,若无则将其管辖范围内顶级域名(如.com)服务器IP告诉本地DNS服务器;
- 顶级域名服务器
顶级域名服务器收到请求后查看区域文件记录,若无则将其管辖范围内主域名服务器的IP地址告诉本地DNS服务器;
- 主域名服务器
主域名服务器接受到请求后查询自己的缓存,如果没有则进入下一级域名服务器进行查找,并重复该步骤直至找到正确纪录;
- 保存结果至缓存
本地域名服务器把返回的结果保存到缓存,以备下一次使用,同时将该结果反馈给客户端,客户端通过这个IP地址与web服务器
简单来说,就是浏览器缓存、操作系统缓存、本地DNS解析器缓存、本地DNS解析器、如果都没有的话,从根域名开始递归搜索。
下面这个图很好的诠释了整个流程
常见面试题:DNS使用UDP还是TCP?
答:都用。
域名解析时使用UDP协议: 客户端向DNS服务器查询域名,一般返回的内容都不超过512字节,用UDP传输即可。不用经过TCP三次握手,这样DNS服务器负载更低,响应更快。 DNS服务器之间互相区域传输用TCP。
CDN(内容分发网络)
加载一些静态资源比如图片的时候,DNS可以返回一个合适的机器的IP给用户,例如可以根据每台机器的负载量,该机器离用户地理位置的距离等等,这种过程就是DNS负载均衡,又叫做DNS重定向。大家耳熟能详的CDN(Content Delivery Network)就是利用DNS的重定向技术,DNS服务器会返回一个跟用户最接近的点的IP地址给用户,CDN节点的服务器负责响应用户的请求,提供所需的内容。
TCP 连接
当浏览器得到了目标服务器的 IP 地址,以及 URL 中给出来端口号(http 协议默认端口号是 80, https 默认端口号是 443),它会调用系统库函数 socket ,请求一个 TCP流套接字。
-
这个请求首先被交给传输层,在传输层请求被封装成 TCP segment。目标端口会被加入头部,源端口会在系统内核的动态端口范围内选取(Linux下是ip_local_port_range) 传输层
-
TCP segment 被送往网络层,网络层会在其中再加入一个 IP 头部,里面包含了目标服务器的IP地址以及本机的IP地址,把它封装成一个IP packet。 网络层
-
这个 TCP packet 接下来会进入链路层,链路层会在封包中加入 frame 头部,里面包含了本地内置网卡的MAC地址以及网关(本地路由器)的 MAC 地址。像前面说的一样,如果内核不知道网关的 MAC 地址,它必须进行 ARP 广播来查询其地址。(ARP查询:根据IP地址获取物理地址的一个TCP/IP协议)
浏览器接受响应
在接收到服务器返回的响应头后,网络进程开始解析响应头,如果发现返回的状态码是301或者302,那么说明服务器需要浏览器重定向到其他URL。这时网络进程会从响应头的Location字段里面读取重定向的地址,然后再发起新的HTTP或者HTTPS请求,一切又重头开始了。
不同Content-Type的后续处理流程也截然不同。如果Content-Type字段的值被浏览器判断为下载类型(比如字节流类型),那么该请求会被提交给浏览器的下载管理器,同时该URL请求的导航流程就此结束。但如果是HTML,那么浏览器则会继续进行导航流程。由于Chrome的页面渲染是运行在渲染进程中的,所以接下来就需要准备渲染进程了。
渲染界面
当服务器提供了资源之后(HTML,CSS,JS,图片等),浏览器会执行一系列复杂的渲染:
-
解析 —— HTML,CSS,JS
-
渲染 —— 构建 DOM 树 -> 渲染 -> 布局 -> 绘制
-
浏览器是一个边解析边渲染的过程。首先浏览器解析HTML文件构建DOM树,然后解析CSS文件构建渲染树,等到渲染树构建完成后,浏览器开始布局渲染树并将其绘制到屏幕上。
因为是后端技术文档,所以就不详细展开了,这里是前端领域的范畴了。想要简单了解可以看下方示意图。
结合上图,一个完整的渲染流程大致可总结为如下:
- 渲染进程将HTML内容转换为能够读懂的DOM树结构。
- 渲染引擎将CSS样式表转化为浏览器可以理解的styleSheets,计算出DOM节点的样式。
- 创建布局树,并计算元素的布局信息。
- 对布局树进行分层,并生成分层树。
- 为每个图层生成绘制列表,并将其提交到合成线程。
- 合成线程将图层分成图块,并在光栅化线程池中将图块转换成位图。
- 合成线程发送绘制图块命令DrawQuad给浏览器进程。
- 浏览器进程根据DrawQuad消息生成页面,并显示到显示器上。
至此,从输入url到页面展示的全流程就结束了,
全流程展示
从图中可以看出,整个过程需要各个进程之间的配合,所以在开始正式流程之前,我们还是先来快速回顾下浏览器进程、渲染进程和网络进程的主要职责。
- 浏览器进程主要负责用户交互、子进程管理等功能。
- 网络进程提供网络下载功能。
- 渲染进程的主要职责是把从网络下载的HTML、JS、CSS、图片等资源解析为可以显示和交互的页面。因为渲染进程所有的内容都是通过网络获取的,会存在一些恶意代码利用浏览器漏洞对系统进行攻击,所以运行在渲染进程里面的代码是不被信任的。Chrome会让渲染进程运行在安全沙箱里,其实就是为了保证系统的安全。
如果想要了解浏览器多进程架构,可以看下《01 | Chrome架构:仅仅打开了1个页面,为什么有4个进程?》这篇文章,来全面了解浏览器多进程架构。
回顾了浏览器的进程架构后,我们再结合上图来看下这个完整的流程,可以看出,整个流程包含了许多步骤,其中几个核心的节点用蓝色背景标记出来了。这个过程可以大致描述为如下。
- 首先,浏览器进程接收到用户输入的URL请求,浏览器进程便将该URL转发给网络进程。
- 然后,在网络进程中发起真正的URL请求。
- 接着就是计算机网络模型的那一层层数据传输。
- 然后网络进程接收到了响应头数据,便解析响应头数据(这里可能遇到重定向,一切又重头开始了),并将数据转发给浏览器进程。
- 浏览器进程接收到网络进程的响应头数据之后,发送“提交导航(CommitNavigation)”消息到渲染进程;
- 渲染进程接收到“提交导航”的消息之后,便开始准备接收HTML数据,接收数据的方式是直接和网络进程建立数据管道;
- 最后渲染进程会向浏览器进程“确认提交”,这是告诉浏览器进程:“已经准备好接受和解析页面数据了”。
- 浏览器进程接收到渲染进程“提交文档”的消息之后,便开始移除之前旧的文档,然后更新浏览器进程中的页面状态。