Web性能优化-什么是多路复用
1. HTTP/2 的帧与流等概念
HTTP/2 是基于二进制帧(Frame),他将一个TCP连接分为若干个流(Stream),每个流中可以传输若干消息(Message),每个消息由若干最小的二进制帧(Frame)组成。
科普:什么是二进制?如果一个二进制人类看得懂,那他就是字符串,否则就是二进制
1 | ------------------- |
前面九个字节代表 Length (长度)、Type (类型)、Flags (标记位)、StreamID (所在流的 ID),第五部分 Payload (数据),一般为16 K - 16 M(这里说的数据不只是请求体,包含了从 HTTP 请求头开始的所有)
与 HTTP/1.* 的区别
GET
- 这里假设是一个 Frame,前面这个框代表前九个字节
- header 代表这是请求头
- + (true) 号代表当前这部分结束
- 冒号开头的表示伪头,h2 现在用这三行表示为以前的请求头第一部分
- 以前的冒号变成了等于号(因为冒号被占用了)
- 大写变成了小写,不允许小写
POST
- 至少三个 Frame
- 第一个 Frame,- END_STREAM 表示请求没有结束,- END_HEADERS 表示请求头也没有结束
- 第二个 Frame,COUTINUATION 表示这是一个继续,要和前面一个一起看,+ END_HEADERS 到我这一帧,请求头结束了
- 以前请求的第三部分(回车),到 h2 就不需要了,删除了
- DATA 数据,+ END_STREAM 代表请求到这里都结束了
响应
总结
基本没什么区别,只不过是吧以前一个请求、一个响应变成了不同的帧,让那九个字节关联起所有的帧,还有伪头的概念
2. HTTP/2的流与多路复用
- 上次说到 HTTP/1.1 管道的概念,之所以不能使用就是因为响应的时候必须要按顺序
- 但是在 HTTP/2 中就没有这个问题了,他每个响应都会告诉你对应的是哪个,因为他有前面 9 个字节可以做标记,所以在管道中每个请求响应都是独立的,大大的提升了效率
- 但是 H2 并不仅仅是加了标记,由于顺序是乱的,所以请求方需要去做一个整合,响应方 Frame 太多了请求方一般还一般需要压缩在发送
- 有了多路复用以后,以前的并行方案就没有必要了,并行的话还要多开好几个连接
- 一个管道中能开多少个“路”呢?答案是 100 可以, 1000 个也可以,一般来说 100 都算少的,所以他的效率是极高的
3. HTTP/2 的 Server Push 的利与弊
先说结论,我们实际生活中并不会或者说很少使用到这个功能
- 首先客户端还是需要先发送第一个请求
- 但是此时服务器会主动多返回一些东西回来
- 当客户端再需要请求这些文件的时候,就会发现已经有了,就不再请求了
那么问题来了,服务器怎么知道客户端需要哪些东西呢?
答案是程序员认为去提前写好的
配置 Server Push
方法一:Nginx
1 | // Nginx |
方法二:Nginx 和 响应头
1 | // Nginx |
1 | // index.html 响应头 |
- 一般这样的配置非常繁琐,如果文件名称变动,还需要后台配合来改配置,一般没人会这么做
- 还有现在的前端都是工程化了,文件名一般都是混合了哈希,后端根本不知道文件名
- 所以几乎没有人用
- 当然 Server Push 很好,可以提前响应,但是现实状况是后台不知道提前去响应什么