网络协议-HTTP性能优化篇
HTTP/1协议
1. 缓存的工作原理
强缓存
-
Expires:值为服务器返回的过期时间,浏览器再次加载资源时,如果在这个过期时间内,则命中强缓存。(HTTP1.0的属性,缺点是客户端和服务器时间不一致会导致命中误差)
-
Cache-Control:HTTP1.1属性,优先级更高,以下为常用属性
- no-store: 禁用缓存
- no-cache:不使用强缓存,每次需向服务器验证缓存是否失效
- private/public:private指的单个用户,public可以被任何中间人、CDN等缓存
- max-age=:max-age是距离请求发起的时间的秒数
- must-revalidate:在缓存过期前可以使用,过期后必须向服务器验证
-
Pragma:
- no-cache:效果和cache-control等no-cache一致。 优先级Pragma > Cache-Control > Expires
强缓存的资源存储位置
| 状态 | Network - Size | 含义 |
|---|---|---|
| 200 | from memory cache | 不请求网络资源,资源在内存, 一般是脚本、字体、图片,浏览器关闭,数据将被释放 |
| 200 | from disk cache | 请求网络资源,资源在磁盘, 一般是css等,关闭数据还在 |
| 200 | 资源大小 | 从服务器下载最新资源 |
| 304 | 报文大小 | 请求服务端发现资源未更新,使用本地资源 |
协商缓存
- 验证响应:
- 验证是通过使用包含
If-Modified-Since或If-None-Match请求标头的条件请求完成的; - 一般使用
Last-Modified/If-Modified-Since请求标头;- 如果请求的资源已更新,客户端将收到
200 OK响应,否则,如果请求的资源尚未更新,则会收到304 Not Modified响应。
- 如果请求的资源已更新,客户端将收到
- 时间格式复杂且难以解析,分布式服务器难以同步文件更新时间。为了解决这些问题,使用
ETag/If-None-Match请求标头。
- 验证是通过使用包含
- 强制重新验证:
- 响应中添加
Cache-Control: no-cache以及Last-Modified和ETag
- 响应中添加
用户行为对强缓存和协商缓存的影响
| 用户操作 | Expires/cache-control | Last-modified/Etag |
|---|---|---|
| 地址栏回车 页面链接跳转 新开窗口 前进、后退 | 有效 | 有效 |
| F5刷新 | 无效 | 有效 |
| Ctrl + F5刷新(强制刷新) | 无效 | 无效 |
2. 解决缓存不一致的乐观锁
- Web并发解决方案-乐观锁,例如:并发提交新文档
3. 设置依赖资源间的过期时间
背景
缓存引发的不一致问题, 例如:html、css、js缓存页面显示不一致
解决方法
- HTML expire in 10s
- CSS、JS never expire
4. 开启多线程下载及断点续传
- 206 Partial Content: 返回完整包体的部分内容
- 416 Range Not Satisfiable: 请求的Range范围与实际的资源大小不匹配
- 200 Ok: 服务器不支持Range请求,故直接返回完整的包体
- 412 Precondition Failed: 客户端缓存资源的Etag(指纹)与当前最新资源不再匹配
5. HTTP资源压缩传输
Nginx配置
gzip on; #是否开启gzip模块 on表示开启 off表示关闭
gzip_buffers 4 16k; #设置压缩所需要的缓冲区大小
gzip_comp_level 6; #压缩级别1-9,数字越大压缩的越好,也越占用CPU时间
gzip_min_length 100k; #设置允许压缩的最小字节
gzip_http_version 1.1; #设置压缩http协议的版本,默认是1.1
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; #设置压缩的文件类型
gzip_vary on; #加上http头信息
Vary: Accept-Encoding #给后端代理服务器识别是否启用 gzip 压缩
HTTP/2协议有哪些优点
HTTP2 Frame格式
- 不会被CRLF攻击:因为不是\r\n分隔语句,Length分隔语句,1k为一帧
- Type: 0为Body帧;1为Header帧;3为RST帧,不要后面的响应
- Stream Identifier 单数(1、3、5、7、9)为客户端发送请求,双数(2、4、6、8、10)为服务器主动发送
总结
- HTTP2通过Frame帧对消息进行了二进制编码,更有效率
- 通过虚拟的Stream层,HTTP2实现了应用层的多路复用功能
- 基于Stream的优先级,HTTP2可以分配资源的使用
- HTTP2可以运行在TCP协议上,也可以运行在TLS/SSL协议上
- Protobuf生成SDK后,可以提供更快速、压缩比更高的算法
- gRPC通过一系列规则,将包、类、错误码等编码进了HTTP2头部