从输入URL到页面加载的全过程是一道经典面试题,也是一道痕宏大的面试题。它可以用简单几句话就把大概流程说完,但是每一个流程都能够展开成一本书。所以想要把这个过程理解透,需要下很大的功夫。
这里我们用先把大致流程列出来,然后按照每一个步骤中能够涉及到的知识点来慢慢展开。
「翻译」互联网是如何运作的?这篇文章中也提到了在浏览器输入URL地址后会发生什么,文章列出了浏览器会做的事情,主要内容围绕浏览器和服务器之间的通信展开,没有细化浏览器接内部机制,这里我们先把步骤列出来,再来细化知识点。
序号 | 内容 | 知识点 |
---|---|---|
1 | 从浏览器接收url到开启网络请求线程 | 浏览器机制,进程与线程之间的关系 |
2 | 开启网络线程到发出一个完整的http请求 | DNS查询,TCP/IP请求,协议栈 |
3 | 从服务器接收到请求到对应后台接收到请求 | 负载均衡,安全拦截,后台内部处理 |
4 | 后台和前台的http交互 | http协议,http报文,cookie |
5 | http缓存 | |
6 | 浏览器接收到http数据包后的解析流程 | html解析,css解析,布局,绘制,复合图层的合成, GPU绘制,外链资源的处理 |
7 | CSS的可视化格式模型 | 元素的渲染规则 |
8 | JS引擎解析过程 | |
9 |
从浏览器接收URL到开启网络请求进程
多进程的浏览器
- 浏览器是多进程的,有一个主进程,每个tab页有一个独立的进程
- 进程包括
- Browser主进程(只有一个)
- 第三方插件进程(仅当使用时创建)
- GPU进程(最多一个,用于3D绘制)
- 浏览器渲染进程(默认每个tab一个)
多线程的浏览器内核
详见:前端复习之事件系统
浏览器渲染进程是浏览器内核,页面渲染、JS执行、时间循环都在这个进程中进行。它是多线程的,包括:
- GUI渲染进程 (负责渲染界面,与JS线程互斥)
- JS引擎线程(负责处理JS脚本)
- 事件触发线程(用来控制时间循环)
- 定时触发器线程(
setTimeout
和setInterval
所在线程) - 异步http请求线程
解析URL
输入URL后,会进行解析。URL一般包括:
protocol
协议头,如http, ftp等host
主机域名或IP地址port
端口号path
目录路径query
查询参数fragment
即#
后的hash值,一般用来定位到某个位置
开启网络线程到发出一个完整的HTTP请求
DNS查询得到IP
DNS全称是Domain Name Service,域名服务。它是一个记录互联网中各计算机名称和与之对应的IP地址的分布式数据库。每个DNS服务器都是数据库的一部分,如果没有查找到域名,就会逐级向上重定向请求,直到找到域名,再连接到服务器。
浏览器会先与服务器建立连接,再发送HTTP请求。
TCP/IP请求
三次握手
浏览器和服务器连接的方式是三次握手。
- 第一次握手:建立连接。客户端发送连接请求报文段
- 第二次握手:服务器接收到报文段,对报文段进行确认,并发送自己的请求信息
- 第三次握手:客户端收到服务器的报文段,向服务器返回报文
简单理解就是:
- 第一次:客户端给服务器发送消息“我想和你聊会天”
- 第二次:服务端收到消息,把自己的状态改为聊天状态,并告诉服务器“我听见了,你能听见我吗?”
- 第三次:客户端收到服务器的消息,回复服务器“我能听见你”
三次握手确保双方发送的信息对方都能收到。
四次挥手
断开连接时,需要经历四次挥手。
- 第一次挥手:客户端给服务端发送报文,告诉服务端要结束连接了,此时客户端进入等待结束状态,表示客户端没有数据要发给服务端了
- 第二次挥手:服务器收到客户端的报文,给客户端回复报文,表示同意关闭请求
- 第三次挥手:服务器向客户端发送报文,请求关闭连接
- 第四次挥手:客户端收到服务器的报文,回复给服务器一个OK的消息,进入倒计时关闭状态,服务器收到OK消息后就关闭连接;此时客户端没有收到回复,表示服务器正常关闭了,于是客户端也关闭连接
简单来说,就是:
- 第一次:客户端说“我要挂电话了”
- 第二次:服务端收到消息,告诉客户端“我同意”
- 第三次:服务端说“那我挂了哦”,就开始举着电话准备挂
- 第四次:客户端说”好,你挂吧“,就开始等着服务端挂电话;服务端听到后就挂了电话;客户端等了一会儿发现没有声音,确定服务端挂了,自己也挂了
网络模型和协议栈
HTTP即超文本传输协议,是应用层协议,它位于协议栈的顶层。当数据包从一个电脑传递到另一个电脑时,数据包会从发送信息的电脑协议栈的顶层开始逐级向下,直到网络接口层将数据从文本信息转化成电子信号,接收信息的电脑则从协议栈的底部开始,数据会逐级向上传递,最终到达应用层。
在协议栈中,TCP和IP依次位于应用层的下面,因此HTTP请求在传递过程中也会逐级通过TCP层和IP层,
从服务器接收到请求到对应后台接收到请求
负载均衡
详见:简单了解负载均衡
HTTP交互
前后端交互时,HTTP报文作为信息的载体。
HTTP报文结构
报文一般包括: 通用头部,请求/响应头部,请求/响应体
通用头部
组成部分:
Request URL
:请求的web服务器地址Request Method
:请求方法(GET,POST,OPTIONS,PUT,HEAD,DELET,CONNECT,TRACE
)Status Code
:请求返回的状态码Remote Address
:请求的远程服务器地址
请求方法
- HTTP 1.0定义了三种请求方法:
GET, POST, HEAD
- HTTP 1.1新增了五种请求方法:
OPTIONS, PUT, DELETE, TRACE, CONNECT
状态码
- 1xx:请求已接受,继续处理
- 2xx:请求被成功接收
- 200: 请求被成功完成,所请求的资源发送回客户端
- 3xx:重定向,要完成请求必须进行更进一步的操作
- 304:自从上次请求后,请求的网页未修改过,请客户端使用本地缓存
- 4xx:客户端错误
- 401:请求未经授权
- 403:禁止访问
- 404:资源未找到
- 5xx:服务器端错误
- 500:服务器内部错误
- 503:服务不可用
请求/响应头部
常用请求头
Accept
: 接受类型,表示浏览器支持的MIME类型Accept-Encoding
: 浏览器支持的压缩类型Content-ype
:实体内容的类型Cache-Control
:指定请求和响应遵循的缓存机制If-Modified-Since
:对应服务端的Last-Modified
,用来查看文件是否变动Expires
:缓存控制,这个时间内不会请求,直接使用缓存Max-age
:代表资源在本地缓存多少秒Cookie
:有cookie并且同域访问会自动带上Connection
:浏览器与服务器通信时对于长连接如何处理Host
:请求的服务器URLOrigin
:最初的请求从哪里发起(源)Referer
:该页面的来源URLUser-Agent
:用户客户端的一些必要信息
常见响应头
Access-Control-Allow-Headers
:服务器允许请求的HeadersAccess-Control-Allow-Methods
:服务器允许的请求方法Access-Control-Allow-Origin
:服务器允许的请求Origin头部Content-Type
:服务器返回的实体内容的类型Date
:数据从服务器发送的事件Cache-Control
:告诉浏览器或其他客户,什么环境可以安全地缓存文档Last-Modified
:请求资源的最后修改时间Expires
:应该在什么时候认为文档已经过期,从而不再缓存它Max-age
:客户端的本地资源应该缓存多少秒Set-Cookie
:设置页面cookieKeep-Alive
:如果客户端有keep-alive,服务端也会有相应Server
:服务器的一些相关信息
请求头和响应头匹配
一般来说,请求头和响应头应该匹配分析。
- 请求头的
Accept
和响应头的Content-Type
匹配 - 跨域请求时,请求头的
Origin
和响应头的Access-Control-Allow-Origin
要匹配 - 使用缓存时,请求头的
If-Modified-Since
,If-None-Match
分别和响应头的Last-Modified
,ETag
对应
请求/响应实体
HTTP请求中,除了头部,还有消息实体。消息头和实体之间会有一个分隔符。
请求头体示例:
Cookie
详见:BOM之cookie
优化cookie
在一个页面下,如果有许多依赖的静态资源,这些资源的HTTP请求都会携带cookie,而这些静态资源并不需要cookie验证,就会造成验证的资源浪费。针对这种场景,可以多域名拆分:
- 将静态资源分组,放到不同的子域名下
- 子域名请求时,不会带上父级域名的cookie,避免浪费资源
长连接和短连接
TCP/IP层面
- 长连接:一个TCP/IP连接上可以连续发送多个数据包,如果连接期间没有数据包发送,需要双发发送检测包来维持连接
- 短连接:通信双方有数据交互时,就建立一个TCP连接,数据发送完成后断开连接
HTTP层面
- HTTP 1.0:默认使用短连接,浏览器每进行一次HTTP操作,就建立一次连接,任务结束就断开
- HTTP 1.1开始:默认使用长连接,长连接中会有
Connection: keep-alive
。长连接情况下,一个网页打开完成后,客户端和服务端之间用于传输HTTP的TCP连接不会关闭。如果客户端再次访问这个服务器页面,会继续使用这一条已经建立的连接
HTTP 2.0
HTTP 2.0是HTTP的下一代规范,它为提升加载速度提供了空间。HTTP 2.0和HTTP 1.x相比,无论在资源加载速度还是CPU占用上都有了很大的提升。
HTTP版本
HTTP协议目前已有3个版本:
- HTTP 1.0
- HTTP 1.1
- HTTP 2.0
版本之间的区别
HTTP 1.0 VS HTTP 1.1
HTTP 1.0和HTTP 1.1之间最主要的区别是:HTTP 1.0默认是短连接,HTTP 1.1默认是长连接。
HTTP 1.0(每次请求资源都要建立连接,每次连接都要三次握手,四次挥手)
HTTP 1.1(建立一次连接,多次请求均由这个连接完成)
除此之外,还有以下改动:
HTTP 1.1增加Host字段
HTTP 1.1引入
Chunked transfer-coding
,实现断点续传HTTP 1.1.管线化(pipelining)理论,可以同时发出多个HTTP请求(但实际操作中还是会多开TCP,而不是HTTP pipelining,下图是管线化和非管线化的区别)
HTTP 2.0
无论HTTP 1.0还是1.1都会出现阻塞的情况,因为无论是一次发送一个请求,还是同时发送多个请求,返回的数据都需要按照响应顺序一一接收。这个阻塞的情况叫做线头阻塞(Head of line blocking)。
- HTTP 2.0解决了线头阻塞的问题,它实现多路复用,即一个TCP/IP连接可以请求多个资源。
HTTP采用新的二进制分帧层(应用层与传输层中间),不再以文本格式传输,定义了如何封装http消息,并在客户端和服务器之间传输。
传输的每个帧都关联到一个“流”,双休的帧序列可以通过一个HTTP2的连接在服务端和客户端之间不断的交换数据。
使用HPACK对头部进行压缩
服务器推送,服务端可以退客户端的一个请求发出多个响应,主动通知客户端
请求优先级(如果流被赋予优先级,就会基于优先级来处理)
HTTPS
https就是安全版的HTTP。
区别
请求前建立SSL连接,确保接下来的通信都是加密的,无法被轻易截取分析。
HTTPS的运行机制见:用信鸽解释HTTPS
解析页面流程
浏览器渲染的大体步骤:
- 解析HTML,构建DOM树
- 解析CSS,生成CSS规则树
- 合并DOM树和CSS规则,生成render树
- 布局render树(Layout/reflow),负责各元素尺寸、位置的计算
- 绘制render树(paint),绘制页面像素信息
- 浏览器会将各层的信息发送给GPU,GPU会将各层合成(composite),显示在屏幕上
详见:HTML解析过程全解
参考: