HTTP/0.9 --> HTTP/1.0 --> HTTP/1.1 --> SPDY --> HTTP/2
主要新特性:
- 首部压缩
- 分帧传输
- 服务端推送
为什么提出HTTP/2?
网页请求的资源越来越大,越来越多,人们对于网页加载的速度的容忍度越来越低,要求越来越高。而HTTP/1.1的协议还是20年前的协议,当时的背景是网页请求数少,网页中资源小。因此,亟需升级协议以提高网站的性能。HTTP/2的主要任务就在于此。
一、HTTP进化史
HTTP/0.9(1989)
- 只有GET请求方法
- ×没有首部
HTTP/1.0(1996)
+首部
+响应码
+重定向
+错误
+条件请求
+内容编码(压缩)
+更多的请求方法(GET POST ...)
......
×缺少强制的Host首部
×不能让多个请求共用一个连接
×缓存的选择简陋
HTTP/1.1(1999)
- +强制客户端提供Host首部,使得虚拟主机托管成为可能(一个IP提供多个服务器)
- +Web服务器不需要在每个响应之后关闭连接,对于提升性能来说有重大意义
- +缓存相关首部的扩展
- +OPTIONS方法
- +Upgrade首部
- +Range请求
- +transfer-encoding
- +管道化(pipelining) ---服务器和代理常常没有实现......
SPDY(2009)
- +多路复用
- +分帧传输
- +首部压缩
HTTP/2.0(2015)
相比于HTTP/1.1
- 可感知的多数延迟能够量化的显著改善
- 解决HTTP中队头阻塞问题
- 通过提升TCP连接利用率实现并行,而非与服务器建立多个连接
- 保留HTTP/1.1的语义(包括:HTTP方法、状态码、URL、首部字段...等等)
- 明确定义HTTP/2.0和HTTP/1.x的交互方法(双向)
二、Web性能优化动机与方式
当前性能挑战
当前web应用每个页面可能引用数百个对象,关联数十个域名,网络环境相差迥异,设备处理能力参差不齐。这种情况下提供表现一致且迅速的web体验不简单。保证用户在网站上交互体验的流畅性,得重视理解客户端获取页面和渲染页面步骤,从而使得在协议上做出的改进实实在在的提升web的性能。
- 更多的字节
- 更多的资源
- 更高的复杂度
- 更多的域名
- 更多的TCP socket
web页面请求
资源请求/获取
把待请求url放入队列 --> 解析url中域名的IP地址 --> 建立与目标TCP连接 --> 如果是HTTPS,初始化并完成TLS握手 --> 向页面对应的url发送请求
资源响应/渲染
接收响应-->是HTML,则解析-->对页面引用进行有限排序-->添加引用资源到请求队列-->等待
-->不是HTML,判断关键资源没有接收完成 --> 等待
关键资源接受完成 --> 渲染页面 --> 还要继续接受其他资源 --> 等待
--> 无其他资源,页面渲染结束
关键性能指标
- 延迟
- 带宽
- DNS查询
- 建立连接时间
- TLS协商时间
- 首字节时间
- 内容下载时间
- 开始渲染时间
- 文档加载完成时间
H1面临的问题
- 队头阻塞
- 低效的TCP利用(拥塞窗口)
- 臃肿的消息首部
- 受限的优先级设置
- 第三方资源限制了加载速度(H2也不可避免)
性能优化技术
DNS查询优化
- 限制域名的数量
- 选择合适的域名服务器
- 利用DNS预取指令,例如预取
ajax.googleapis.com
:页面中加入标签<link rel="dns-prefetch" href="//ajax.googleapis.com">
, 这样在下载处理主页面的同时,预取指令就能开始解析指定的域名。
优化TCP连接
- 利用preconnect指令,如同DNS预取指令:
<link rel="preconnect" href="//fonts.example.com">
- 借助CDN,使用户请求的资源尽可能近,这样可以更快获得响应因而更快终止当前连接,减少后续建立新连接的延时。
避免重定向
- 利用CDN代替客户端在云端实现重定向
- 同一域名重定向,在Web服务器端处理(rewrite规则),避免重定向。
客户端缓存
客户端缓存TTL(生存时间),设置HTTP首部cache-control及max-age(单位秒),或者expires首部。
网络边缘缓存
hold'til told!
条件缓存
304 Not Modified状态码,若请求资源发生了变化,则直接返回资源;若请求资源未发生变化,则直接返回内容没变的提示消息:HTTP首部包含Last-Modified-Since, 请求体中包含实体校验码ETag。
压缩和代码极简化
极简化 --> 无损压缩(gzip,deflate, brotli)
CSS资源放在JS资源和图片之前
- 定期清理不需要的JS资源
- 如果JS执行顺序无关紧要,并且必须在onload之前运行,可以设置async属性,这样就可以并行下载JS。
- 如果JS执行顺寻很重要,并且在DOM加载完成后执行,可以设置defer属性。
- 不影响页面初次展示的页面,onload事件触发后执行。
图片优化
- 取出图片中地理位置、时间戳等元信息
- 针对于image overloading,可以使用技术手段根据用户设备情况提供剪裁过的图片。
反模式
针对于HTTP/1.1适用,但对于H2来说适得其反的做法,因为HTTP/2对于每个域名只会开启一个连接。HTTP/2可以并行处理多个请求。
- 生成精灵图和资源合并/内联
- 域名拆分
- 禁用cookie域名