浏览器的组成
了解浏览器的运行,首先要先了解浏览器的组成。浏览器由shell
(命令解析代理,简单来说就是代理用户对内核的操作
)和浏览器内核
组成。
shell 组成:
- 用户界面:除浏览器请求的页面以外,都属于用户界面。
- 网络:用于网络请求,包含多种文件传输协议,如HTTP、FTP等。
- UI后端:用于绘制’‘对话框’'等基本组件。
- JS解释器:解释并执行网页中的javascript代码
- XML解析器:将XML文档解析成文档对象模型(DOM)
- 数据存储:将浏览器数据存储在硬盘上
内核组成:
- 浏览器引擎:为渲染引擎提供高级接口
- 渲染引擎:负责显示请求的内容。负责解析请求到的HTML、CSS 并将其显示
浏览器的进程
除了浏览器的组成,在谈到一段程序在计算机中的运行时,那必须提到进程
和线程
的概念
- 进程(资源分配的最小单位):一个
执行中程序
的实例
早期单道批操作系统
的计算机,仅执行一个程序,由其分配所有的系统资源,利用率非常低。后改进为多道批操作系统
,可以在内存中同时加载多道程序并发执行,在某个程序需要等待资源时,CPU会去执行其他程序,但因为各个程序共享资源,导致经常出现资源冲突问题。因此提出了进程
的概念,只有进程可以申请系统资源,进程间不会共享资源。系统通过PCB(process control block)对进程进行管理和调度。
- 线程(CPU调度的最小单位):线程是进程中的一个实体
因为进程的创建、销毁与切换存在着较大的时空开销,因此提出了线程
来减少开销。同一进程间的线程共享进程的资源。因为线程是进程的的组成部分,所以线程的管理(通过线程控制块TCB)可以有两种选择,一种是让进程自己管理线程(用户态线程),另一种是通过操作系统管理线程(内核态线程),但用于两种选择都有缺陷,现代操作系统选择将二者结合起来,用户态的执行系统负责进程内部线程在非阻塞时的切换;内核态的操作系统负责阻塞线程的切换,即同时实现内核态和用户态线程管理。
当线程未阻塞时,由用户态对线程进行切换,当线程发生中断或异常时,切换到内核态执行中断处理。
浏览器常见的进程有以下几种:
- Browser进程:浏览器的主进程,负责协调控制浏览器
- GPU进程:用于3D绘制等
- Network进程:负责发起接受网络请求
- Storage进程:从原来的主进程中分离出来的缓存服务,主要负责提供浏览器本地存储等功能
- 渲染进程:负责控制显示tab标签页的内容
- 插件进程:使用插件时创建的进程
其中渲染进程含有5个主要线程
- GUI渲染线程:负责渲染页面、解析Html和Css、构建DOM树、CSSOM树、Render树、绘制页面、重绘重排
- JS引擎线程:负责解析Javascript脚本,运行代码。与GUI渲染线程互斥
- 定时器线程:setInterval和setTimeout,因为JS引擎是单线程,如果处于阻塞状态会影响定时器的准确性,计时完毕后,添加到事件队列中,等待JS引擎空闲后执行
- 异步http请求线程: 当XMLHttpRequest连接后,浏览器新开的一个线程,当检测到状态变化,将回调放入事件队列中,等待JS引擎执行。
- 事件触发线程:主要用来控制事件循环(event-loop),将对应任务添加到事件触发线程中,在对应事件符合触发条件触发时,就把事件添加到待处理队列的队尾,等JS引擎处理
浏览器的网络请求
浏览器在输入网址到解析页面的过程中包含了一系列的网络请求
(1)解析URL: 首先对 URL 进行解析,定位资源路径。
//统一资源定位符(URL)的语法规则
scheme://host.domain:port/path/filename
scheme - 定义因特网服务的类型。常见的协议有 http、https、ftp、file
host - 定义域主机(http 的默认主机是 www)
domain - 定义因特网域名,比如 w3school.com.cn
port - 定义主机上的端口号(http 的默认端口号是80)
path - 定义服务器上的路径(如果省略,则文档必须位于网站的根目录中)
filename - 定义文档/资源的名称
如果URL不合法,会将地址栏中的内容传递给搜索引擎。此外,浏览器会对其中的非法字符进行转译,如admin等
(2)缓存判断:
从缓存位置来看,缓存分为四种,从上到下依次查看是否命中
Service Worker 是运行在浏览器背后的独立线程,一般用来实现缓存功能。传输协议必须为HTTPS
Memory Cache 内存缓存,一旦关闭 Tab 页面,缓存会被释放
Disk Cache 硬盘缓存,读取速度慢,容量和存储时效性高,大部分缓存都来自Disk Cache,在HTTP的协议头中设置
Push Cache 推送缓存,HTTP/2 中的内容,当以上三种缓存都没有命中时,才被使用。只在会话(Session)中存在,一旦会话结束就被释放
浏览器对于所请求资源的缓存处理主要包含以下三个策略:存储策略、过期策略、协商策略。其中,存储策略发生在收到请求响应后,用于决定是否缓存相应资源;过期策略发生在请求前,用于判断缓存是否过期;协商策略发生在请求中,用于判断缓存资源是否更新。 详见浏览器缓存策略
在面对一个具体的http缓存需求时,决策流程图如下:
1.资源内容是否可以复用,Cache-Control设置为no-store
2.是否每次都需要向服务器进行缓存有效确认,Cache-Control设置为no-cache
3.资源是否可以被代理服务器缓存,设置为 private or public
4.资源的过期时间,设置对应的 max-age值
5.配置协商缓存需要用到的 Etag、Last-Modified 等参数
(3)DNS解析:判断本地是否有该域名的 IP 地址的缓存,有则使用,如果没有则向本地 DNS 服务器发起请求。本地 DNS 服务器检查是否存在缓存,没有则向根域名服务器发起请求,依次递归向高级域名服务器查询,最终获得域名的 IP 地址后,本地 DNS 服务器将该 IP 地址返回给用户。
(4)获取MAC地址: 获取到 IP 地址后,数据传输还需要目的主机 MAC 地址(用于数据链路层的通信),获取MAC地址主要通过ARP协议(地址解析协议,ipv4网络层的必备协议,在ipv6中已经被替换为邻居发现协议NDP),首先查看目标 IP 是否在自己的ARP表中,若不存在,则判断目标IP与自己是否在同一网段,若在同一网段,发送ARP广播报文,去请求解析出目标MAC地址,目标主机给出应答。否则,发送ARP广播报文,ARP包目标MAC地址是网关MAC地址,网关会给出应答。
(5)TCP三次握手: 下面是 TCP 建立连接的三次握手的过程
-
首先客户端向服务器发送一个 SYN 连接请求报文段和一个随机序号
-
服务端接收到请求后向服务器端发送一个报文段,确认连接请求,并向客户端发送另一个随机序号。
-
客户端接收服务器的确认应答后,进入连接建立的状态,同时向服务器也发送一个ACK 确认报文段,服务器端接收到确认后,也进入连接建立状态
ps:a(喂,听得到吗),b(听到了,你听得到我吗),a(听到了,我们开始聊天吧)
(6)HTTPS握手: 如果使用 HTTPS 协议,在通信前还存在TLS 四次握手(详见https加密原理握手过程详解)过程。
- 客户端告诉给服务端,加密协议版本,加密套件(如RSA),和一个**
客户端随机数
** - 服务端告诉客户端,一个**
服务器随机数
** + 服务器证书(CA) + 确定的加密协议版本 -
- 客户端生成新随机数,
pre_master_key
。从服务器证书里取公钥,用公钥加密pre_master_key
,发给服务器。 - 并使用个随机数进行计算得到一个会话秘钥。并通知服务端,后续用这个会话秘钥进行对称加密通信。
- 客户端把迄今为止的通信数据内容生成一个摘要,用会话秘钥加密,发给服务器做校验
- 客户端生成新随机数,
-
- 服务端拿到客户端传来的**
pre_master_key
,跟客户端一样,用这三个随机数同样获得一个会话秘钥**。并告诉客户端,后续用这个"会话秘钥"进行加密通信。 - 服务端将迄今为止的通信数据内容生成一个摘要,用会话秘钥加密一下,发给客户端做校验
- 服务端拿到客户端传来的**
(7)返回数据: 页面请求发送到服务器端后,服务器端返回相关文件作为响应,浏览器接收到响应后,对相关文件进行解析
(8)页面渲染: 浏览器根据 html 文件构建 DOM 树,根据 css 文件构建 CSSOM 树,后根据 DOM 树和 CSSOM 树建立渲染树。后根据渲染树进行布局。布局完成后,使用 UI 接口对页面进行绘制。
(9)TCP四次挥手: 下面是 TCP 断开连接的四次挥手过程。
- 客户端发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,seq=u
- 服务器端接收到连接释放报文后,发出确认报文,ACK=1,ack=u+1,seq=v
- 客户端收到确认请求后,客户端进入FIN-WAIT-2状态,等待服务器发送连接释放报文,服务器将数据发送完毕后,向客户端发送连接释放报文,服务器进入LAST-ACK状态,等待客户端的确认
- 客户端收到连接释放报文后,发出确认报文,ACK=1,ack=w+1,seq=u+1,后进入TIME-WAIT状态,但此时TCP连接还未终止,经过2MSL后,客户端进入CLOSED状态,服务器端收到确认报文后,进入CLOSED关闭状态
ps:a(那我先走了),b(好的,你走吧),b(我也走了),a(好的,拜拜)
浏览器的渲染过程
-
Html解析,解析DOM树
将原始字符转换成对应的节点对象,后将节点对象构建成树状结构
-
CSS解析,生成CSSOM树
-
Render Tree
将DOM树和CSSOM树结合形成渲染树
-
layout
根据已知的节点和样式,计算节点在浏览器中的大小和位置
从渲染树根节点开始遍历,用盒子模型表示各节点之间的距离,确定其位置和大小
-
Paint
将渲染树绘制
load和DomContentload事件
load:在所有资源加载完成后触发
domcontentload:在html被解析完成(解析到html结束位置,async不计算在该时间内)后触发
js和css对渲染的影响
js会阻碍DOM树生成,阻碍图片,js,css等资源的加载
js异步加载方式如下:
defer:在文档加载完后执行,在domcontentload前
async:文档加载与执行和js加载与执行是并行执行的
css会阻塞CSSOM生成,阻碍页面渲染,阻碍js执行