HTTP请求的流程
- 构建请求的URL:http协议+主机名+端口号+search
- 查找缓存:cache-control/If-None-Match,强缓存,协商缓存
- DNS解析: 通过域名查找IP地址
- 等待TCP队列:同一域名最多六个队列
- 建立TCP连接:三次握手(SYN、ACK)
- 发送HTTP请求:请求行(方法+URI+HTTP版本),请求头+请求体
- 服务器处理请求:服务器回复响应行(HTTP版本+状态码)
- 服务器响应请求:响应头(返回时间+数据类型+cookie)+响应体(HTML...)
- 浏览器解析与绘制:DOM、Style、Layout、Layer、Paint、tiles、raster、draw quad
- 断开TCP连接:保持打开connection:keep-alive,四次挥手(FIN、ACK、seq、ack)
- 重定向:当状态码为(301/302)时,Location为重定向地址
1 构建请求URL
URL(Uniform Resource Locator)统一资源定位符,用于互联网资源定位,俗称网址
1.1 URL组成部分:
- 【https://】:protocal协议
- 【name.com】:hostname主机名
- 【8080】:port端口号
- 【?params=false】:search
1.2 键入URL后会对URL进行判断搜索:
- 检查URL是否合法
- 合法,则检查URL是否完整(若不完整则对域进行猜测,补全前缀/后缀)
- 不合法,则将键入内容作为搜索条件,使用默认搜索引擎进行搜索
2 查找缓存
查找是否存在缓存,并拦截请求。
优点:
- 缓解服务端压力
- 网站实现快速加载
- 无缓存:若缓存为空则继续请求服务器
- 强缓存:若缓存不为空,则判断
cache-control/Expire是否在有效期 - 协商缓存:判断由服务器决定是否使用缓存,通过
Last-Modified/If-Modified-Since和Etag/If-None-Match判断资源是否更新,若协商缓存失效则返回200,并重新返回资源和缓存标识;若协商缓存生效则返回304,从缓存中读取资源。
note:协商缓存前,要经过DNS域名解析和TCP连接。
缓存位置:
- Service Worker:浏览器独立线程进行缓存
- Memory Cache:内存缓存--F5
- Disk Cache:硬盘缓存--Ctrl+F5
- Push Cache:推送缓存(HTTP/2中的)
3 DNS解析
DNS(Domain Name System) 域名系统
- DNS协议运行在UDP协议之上
- DNS解析,通过域名查找到对应的IP地址
- DNS缓存,浏览器、操作系统、路由器、本地DNS、根域名服务器均有一定缓存
解析流程:
- 查找
浏览器缓存和本地host文件,是否有该网址记录 - 查找
本地DNS缓存,是否有该网址记录 - 根据TCP/IP参数设置的DNS服务器查询,是否在
本地配置区资源中 - 查找
本地DNS服务器是否缓存 - 本地DNS服务器发送查询,至
根DNS服务器;根DNS收到请求后,用顶级域DNS服务器地址进行响应 - 本地DNS服务器发送查询,至
顶级域DNS服务器;顶级域DNS收到请求后,用权威DNS服务器地址进行响应 - 本地DNS服务器发送查询,至
权威DNS服务器;权威DNS收到请求后,用url的IP地址进行响应,完成域名解析。
查询通常,从请求主机到本地DNS服务器查询是递归查询,DNS服务器获取到映射查询是迭代查询。
DNS优化:
- 减少DNS次数;
- DNS预获取,在DOM之前先缓存在本地
- DNS负载均衡,根据机器负载量、地理位置处理
- DNS查找数量=Web页面唯一主机名数量,减少主机名达到减少DNS查找目的( 减少主机名会潜在减少页面并行下载数量,一个主机名推荐2~4组件)
4 建立TCP链接
几乎所有的HTTP链接均由TCP/IP完成,TCP/IP是全球计算机及网络设备都在使用的一种常用的分组交换网络分层,HTTP的连接实际就是TCP连接以及其使用规则。 --《HTTP权威指南》
当浏览器获取到服务器的IP地址以后,浏览器将使用一个随机端口(1024~65524)向服务器80端口发起TCP连接请求(note:HTTP端口默认为80,HTTPS端口默认为443),通过TCP三次握手建立连接。
4.1 分层模型
| [OSI] | [TCP/IP] | ||
|---|---|---|---|
| 7 | 应用层 | HTTP | |
| 6 | 表示层 | 应用层 | |
| 5 | 会话层 | ||
| 4 | 传输层 | 传输层 | TCP TLS |
| 3 | 网络层 | 网络层 | IP |
| 2 | 数据链路层 | 链路层 | |
| 1 | 物理层 |
4.2 TCP三次握手
SYN:握手信号(Synchronize Sequence Number)
ACK:确认应答 (Acknowledgement)
- CLient -> Server : SYN(1)/seq(=j) 客户端请求链接,SYN_SEND
- Server -> CLient : ACK(1)/ack(=j+1)/SYN(1)/seq(=k) 服务器确认应答,SYN-RECV
- Client -> Server : ACK(1)/ack(=k+1)/seq(=j) 客户端确认应答,均ESTABLISHED
note: 三次握手原因:确认CLient和Server均有发送和接收的功能。
4.4 TLS协商
TLS协议(Transport Layer Security):保证通信保密性和数据完整性
- TLS记录协议(TLS Record)
- TLS握手协议(TLS Handshake)
SSL协议(Secure Socket Layer):
- 认证用户和服务,确保发送至正确的客户端和服务器
- 加密数据,防止窃取
- 维护数据完整性,确保传输后不变
TLS握手协议
- CLient -> Server : client hello,携带信息包括:SSL/TLS版本,加密算法,数据压缩方法,随机数A
- Server -> CLient : server hello,携带信息包括:SSL/TLS版本,会话ID,随机数B,服务端数字证书serverCA,客户端证书请求(client certificate request)
- CLient -> Server : 客户端校验serverCA,校验通过则发送随机数C(pre-master-key),使用数字证书中的公钥加密后发出,发出客户端证书clientCA,发出使用私钥加密的随机数clientRandom
- Server -> CLient : 服务端校验clientCA,并解密clientRandom,根据随机数A/B/C(pre-master-key),产生动态密钥(master-key),发送加密的finish消息
- Client -> Server : 客户端根据随机数和算法生成master-key,发送加密的finish消息
服务端和客户端握手完成后,之后的数据均采用master-key进行加密传输。
5 服务器响应
当TCP连接成功后,浏览器会发送一个HTTP GET请求,请求目标通常是一个HTML文件;而服务器收到请求后,调用数据库信息,返回一个HTTP响应报文,内容包括响应头+HTML正文。
note: 当TCP连接后,需要等待TCP队列,同一域名最多建立6个TCP队列
5.1 状态码
由三位数构成,第一位表示响应类别:
- 1XX 指示信息,表示请求已接受,继续处理
- 2XX 成功,表示请求被成功接收、理解、接收
- 3XX 重定向,完成请求需要进一步操作
- 4XX 客户端错误,请求有语法错误,或请求无法完成
- 5XX 服务端错误,服务器未能完成合法请求
5.2 常见请求头和字段
- Cache-Control:must-revalidate、no-cache、private(是否需要缓存资源)
- Connection:keep-alive(保持连接)
- Content-Encoding:gzip(web 服务器支持的返回内容压缩编码类型)
- Content-Type:text/html;charset=UTF-8(文件类型和字符编码格式)
- Date:Sun, 21 Sep 2021 06:18:21 GMT(服务器消息发出的时间)
- Transfer-Encoding:chunked(服务器发送的资源的方式是分块发送)
5.3 HTTP响应报文
响应报文由四部分组成(响应行 + 响应头 + 空行 + 响应体)
- 状态行:HTTP 版本 + 空格 + 状态码 + 空格 + 状态码描述 + 回车符(CR) + 换行符(LF)
- 响应头:字段名 + 冒号 + 值 + 回车符 + 换行符
- 空行:回车符 + 换行符
- 响应体:由用户自定义添加,如 post 的 body 等
6 浏览器解析与绘制
- DOM:处理HTML标记,构建DOM树(DOM Tree)
- Style:计算样式,转换为样式表(Style Sheets),计算DOM各节点的具体样式,构建CSSOM
- Layout:计算元素几何位置,构建布局树(Layout Tree)
- Layer:层叠上下文属性,或剪裁创建图层,构建分层树(Layer Tree)
- Paint:提交Paint List至合成线程
- Tiles:将图层分为图块(tile),通常为256256,512512
- Raster:栅格化,生成位图,视口附近的图块优先渲染,GPU(进程)加速
- Draw Quad:合成,浏览器显示
note:
- DOM解析线程和CSS解析线程为并行的
7 TCP断开连接
设置持久连接(keep-alive),可以优化请求的耗时,关闭TCP连接是一个全双工过程,一般由客户端发起,发包顺序不一定:
- CLient -> Server : FIN(1)/seq(=u) 客户端请求关闭连接,FIN-WAIT-1,发送关闭
- Server -> CLient : ACK(1)/ack(=u+1)/seq(v) 服务器确认应答,并发送ACK和seq,CLOSE-WAIT,客户端收到后进入FIN-WAIT-2,等待服务器完成最后发送
- Server -> CLient : FIN(1)/ACK(1)/ack(=u+1)/seq(w) 服务器发送FIN,请求关闭,LAST-ACK
- Client -> Server : ACK(1)/ack(w+1)/seq(u+1) 客户端确认应答,进入TIME-WAIT(2msl),服务器收到后,均进入CLOSED状态,完成四次挥手
note:四次挥手原因,确保服务器未收到客户端响应时能重新发送请求,保证客户端最后一个ACK服务器能收到
参考原文: 浏览器从输入网址到页面展示的过程