http网络层优化
第一步 url 解析
1.协议:TCP/IP
- TCP 传输通道 路
- HTTP 传输协议 快递小哥
- HTTPS SSL/TSL
- FTP 传输一些大文件
2.端口号
HTTP 80
HTTPS 443
FTP 21
3.编码
对整个url编码:处理空格/中文…
encodeURI/decodeURI
主要对传递的参数信息进行编码
encodeURIComponent/decodeURIComponent
========================================
其他
escape()
unescape()
URI/URL/URN
第二步 缓存检查
1.分为强缓存/协商缓存
先检查是否存在强缓存
- 有,且未失效,走强缓存
- 如果没有,或者失效,检查是否有协商缓存
2.缓存位置
- Memory Cache:内存缓存—内存条
- 加载js,ESCtack,栈内存
- 浏览器一关闭,就没有了
- Disk Cache:硬盘缓存
3.缓存使用先后
-
打开网页:查找disk cache中是否匹配,如有则使用,如果没有则发送网络请求 -
普通刷新(F5):因TAB没有关闭,因此memory cache是可用的,会被优先使用,其次才是disk cache -
强制刷新(Ctrl + F5):浏览器不使用缓存,因此发送的请求头部均带有Cache-control:no-cache,服务器直接返回200和最新内容 -
注意 强缓存和协商缓存的配置 是在后台设置 浏览器 帮助我们实现 前端不需要自己写代码
4.强缓存处理
浏览器对于强缓存的处理:根据第一次请求资源时返回的响应头来确定
- Expires: 缓存过期时间,用来指定资源到期的时间(HTTP/1.0)
- Cache-Control:cache-control:max-age=2592000第一次拿到资源后的第2592000秒内(30天),再次发送请求,读取缓存中的信息(HTTP/1.1)
- 两者同时存在的话,Cache-Control优先级高于Expires
5.强缓存流程
- 客户端发起请求,检测缓存信息和缓存标识Expires Cache-Control
- 有(且未过期):客户端直接读取渲染缓存信息
- 没有(或者过期):客户端重新向服务器发送新的Http请求
-
服务器返回该请求结果和缓存标识 Cache-Control Expires -
客户端把请求结果和缓存标识存储到浏览器中
- 注意
html页面一般不做强缓存 原因:强缓存有问题
6.如果服务器文件更新了,但是本地还是有缓存,这样就拿不到最新的信息了么?
html页面一般不做强缓存
-
每一次html请求都是正常的http请求
- 服务器更新资源后,让资源名称和之前不一样,这样页面导入全新的资源
index.dads22222.js index.fsdesse23.js webpack打包静态资源会加上文件hash name - 当文件更新后,我们在html导入的时候,设置一个后缀(时间戳)
-----------别用强缓存
7.协商缓存 Last-Modified(1.0)/ETag(1.0)
协商缓存就是强缓存失效后,浏览器写的缓存标识向服务器发送请求,由服务器根据缓存标识决定是否使用缓存的过程
- Last-Modified 精确到秒 一秒内完成了资源的返回和资源的更新
- 客户端携带获取的缓存标识发送http请求If-Modified-Since/If-None-Match
服务器根据资源文件是否更新
- 没更新 返回304,通知客户端读取缓存信息
- 更新过,返回200及最新资源信息,已经Last-Modified/ETag
客户端
- 200:直接渲染,并且把最新的结果和标识缓存到本地
- 304:从本地缓存中获取内存进行渲染
8.协商缓存和强缓存的区别
协商缓存总会和服务器协商,所以一定要发http请求
*
第一次向服务器发送请求
*
客户端拿到信息后渲染
*
第二次发请求
- If-Modified-Since = Last-Modified值
- If-None-Match = ETag值
给服务器
*
服务器根据标识判断文件是否更新
*
注:node 如果走协商缓存 需要设置响应头
======================================
一般情况下是强缓存+协商缓存
针对于我们的静态资源文件,而且是不经常更新的
其他:
ajax 获取数据
数据缓存 localStorage vuex或redux
客户端
- 检测本地缓存的数据信息
- 缓存
- 有,且未过期,直接根据本地的数据进行渲染
- 没有,或者过期,基于ajax从服务器获取最新的数据信息
服务器
客户端
第三步 DNS解析
客户端->浏览器缓存->本地hosts文件->本地DNS解析器缓存->本地DNS服务器
域名解析 域名 外网IP
每一次DNS解析事件预计在20~120毫秒
- 减少DNS请求次数 (一个页面中尽可能少用不同的域名:资源放在相同的服务器上,不推荐,项目中往往把不同的资源放在不同的服务器上)
- DNS预获取(DNS Prefetch)
sources查看服务器
服务器拆分的优势
多服务器集群
第四步 TCP三次握手
- seq序号,用来标识从TCP源端向目的端发送的字节流,发送方发送数据时对此进行标记
- ack确认序号,只有ack标志位为1时,确认序号字段才有效,ack=seq+1
- 标志位
- ACK 确认序号有效
- RST 重置连接
- SYN 发起一个新连接
- FIN 释放一个连接
为啥是三次握手而不是二次或者四次?
TCP作为一种可靠传输控制协议,其核心思想:既要保证数据可靠传输,又要提高传输的效率。
二次太少,四次太多
UIP 非可靠的 即时通讯
第五步 数据传输
第六步 TCP四次挥手
客户端和服务端建立好连接通道后,客户端把数据传递给服务器
开始发送释放TCP的操作
服务器 返回给客户端信息
为什么连接的时候是三次握手,关闭的时候却是四次挥手
- 服务端手动客户端的SYN连接请求报文后,可以直接发送SYN+ACK报文
- 但是关闭连接时,当服务端收到FIN报文时,很可能并不会立即关闭链接,所以只能先回复一个ACK报文,告诉客户端:你发送的FIN报文我收到了,只有等到服务器所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送,故需要四次握手
Connection:keep-alive
TCP通道建立完成以后,可以不关闭
HTTP1.0需要自己手动设置
HTTP1.1版本会,规范默认设置
第七步,页面渲染
其他:
-
多路复用
- HTTP/1.0 每次请求响应,建立一个TCP连接,用完关闭
- HTTP/1.1 长链接,若干个请求排队串行化单线程处理,后面的请求等待前面请求的返回才能获得执行机会,一旦有某个请求超时等,后续请求只能被阻塞,毫无办法,也就是常说的线头阻塞。
- HTTP/2.0 多路复用,多个请求可同时在一个连接上并行执行,某个请求任务耗时严重,不会影响到其他连接的正常执行
-
HTTP2.0和HTTP1.x相比的新特性
-
新的二进制格式(Binary Format) HTTP1.x的解析是基于文本基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认0和1的组合,基于这种考虑HTTP2.0协议解析决定采用二进制格式,实现方便且健壮 -
header压缩 HTTP1.x的header带有大量信息,而且每次都要重复发送,HTTP2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header files 表,既避免了重复的header的传输,又减少了需要传输的大小 -
服务器推送 例如我的网页有一个style.css请求,在客户端收到style.css数据的同时,服务端会将style.js的文件推送给客户端,当客户端再次尝试获取style.js时就可以直接从环城中获取到,不用在发送请求了 //通过在应用生成HTTP响应头信息中设置LINK命令 LINK:</style.css>;rel=preload; as=style,</example.png>;rel=preload;as=image -
HTTP1.0和HTTP1.1的一些区别
- 缓存处理
- 带宽优化及网络连接的使用
- 错误通知的管理
- HOST头处理
- 长连接
总结***
1.利用缓存
- 对静态资源文件实现强缓存和协商缓存(扩展:文件有更新,如何保证及时刷新)
- 对于不经常更新的接口数据采用本地存储做数据缓存(扩展:cookie/localStorage/vuex/redx区别)
2.DNS优化
- 分服务器部署,增加HTTP并发性(导致dns解析变慢)
- DNS Prefetch
3.TCP三次握手和四次挥手
4.数据传输
- 建设数据传输的大小
- 内容或者数据压缩(webpack等)
- 服务器端一定要开启GZIP压缩(一般能压缩60%左右)
- 大批量数据分批次请求(例如:下拉刷新或者分页,保证首次加载数据少)
- 减少HTTP请求的次数
- 资源文件的合并
- 字体图标
- 雪碧图CSS-Sprit
- 图片base64
5.CDN服务器"地域分布式"
6.采用HTTP2.0
=======
问题: 第一次页面加载如何减少白屏和等待时间
- LOADDING
- 骨架屏:客户端骨架屏 + 服务端骨架屏
- 图片延迟加载
|