vlambda博客
学习文章列表

一张图了解HTTP协议

一张图:


HTTP1.0

1.0以前的版本已经过时,1.0是第一个指定版本号的协议版本,至今仍然有人在用。

它与0.9相比,增加了POSTPUT等方法,客户端可以向服务器传递的信息变多。

HTTP1.1

优势在哪里?

1. 长连接

1.0版本性能上有一个很大的问题,那就是每发起一个请求,都需要新建一次TCP连接(三次握手)而且是串行的请求,一个请求发出去响应回来了之后才可以发送第二个请求。然后不断地进行TCP建连和TCP断连。通信的开销是非常大的。

为了解决上述问题,1.1提出来了长连接的通信方式。也就是keep-alive功能。

TCPkeepaliveHTTPkeep-alive有什么区别?

HTTP协议的Keep-Alive意图在于短时间内连接复用,希望可以短时间内在同一个连接上进行多次请求/响应。

TCPKeepAlive机制意图在于保活、心跳,检测连接错误。当一个TCP连接两端长时间没有数据传输时(通常默认配置是2小时),发送keepalive探针,探测链接是否存活。

2. Pipeline

可在同一个TCP连接里,客户端可以同时发送多个请求,举例来说,客户端需要请求两个资源,以前的做法是,同一个TCP连接里,先发送A请求,然后等待服务器做出响应,收到后再发出B请求,管道机制(pipeline)则允许浏览器同时发出A请求和B请求。

还有哪些瓶颈?

1. 只有body压缩,没有Header压缩,首部消息越多延迟越大。

HTTP/1 中,HTTP 请求和响应都是由「状态行、请求 / 响应头部、消息主体」三部分组成。一般而言,消息主体都会经过 gzip 压缩,或者本身传输的就是压缩过后的二进制文件(例如图片、音频),但状态行和头部却没有经过任何压缩,直接以纯文本传输。

随着 Web 功能越来越复杂,每个页面产生的请求数也越来越多,根据 HTTP Archive 的统计,当前平均每个页面都会产生上百个请求。越来越多的请求导致消耗在头部的流量越来越多,尤其是每次都要传输 UserAgentCookie 这类不会频繁变动的内容,完全是一种浪费。

2. 每次发送相同的Header,造成带宽的浪费

3. 队头阻塞

HTTP/1.1通过pipelining管道技术实现一次性发送多个请求,以期提高吞吐和性能,如上图中的序列2。然而,这种技术在接收响应时,要求必须按照发送请求的顺序返回。如果,第一个请求被堵塞了,则后面的请求即使处理完毕了,也需要等待。

就好比上班路上的塞车。

4. 服务器无法主动推送

5. 没有请求优先级控制

怎么优化呢?

1. 尽量避免发送HTTP请求

缓存技术:对于一些具有重复性的HTTP请求,比如每次请求得到的数据都是一样的,那我们可以把这对“请求-响应”的数据缓存中本地,那么下次就直接读取本地的数据,没有必要在通过网络获取服务器的响应。缓存技术,HTTP1.1的性能得到了肉眼可见的提升。

客户端会把第一次请求以及响应的数据保存在本地磁盘上,其中将请求的URL作为key,而响应作为value,两者形成映射关系。

缓存也有一个过期的时间,服务器在发送HTTP响应时,会估算一个过期的时间,并把这个信息放在响应头中,这样客户端在查看响应头部的时候,一旦发现缓存中的响应是过期的,就会重新发送网络请求。留一个问题,如果客户端此时重新发送的网络请求,假设服务器上的资源并没有变更,还是原来的老样子,那么服务器应该怎么处理呢?这里不再详细描述,大家可以自行查一下HTTP的返回码304.

 

一张图了解HTTP协议


2. 在需要发送HTTP请求时,考虑如何减少请求次数

减少重定向的次数。

还有一种情况,服务端一方往往不止一台服务器,比如源服务器上一级是代理服务器,代理服务器与客户端直接进行通信。

 

一张图了解HTTP协议


此时重定向的工作如果交给代理服务器完成,就能减少HTTP请求的次数。

一张图了解HTTP协议


减少HTTP响应的大小

可以对HTTP的响应进行压缩

 

合并请求:首先,把小文件小资源的请求合并成一个大的请求,虽然传输的总资源不变,但是可以减少请求,减少重复发送的HTTP头部。其次,1.1一般会同时发送多个请求,那么为了避免队头阻塞,会通过多条连接进行发送,合并请求,也会减少TCP连接的数量,省去了TCP的三次握手的时间。

延迟发送请求

请求网页的时候,没必要把全部的资源都获取到,可以只获取当前页面的资源,当用户向下滑动或者翻页的时候,再获取接下来的资源。

3. 减少服务器HTTP的响应的数据大小

对资源进行压缩。有损压缩和无损压缩。有损压缩一般用户压缩多媒体数据,比如音频 视频 图片等,可以牺牲一部分质量,比如像素。

HTTP2.0

有哪些优化?

1. Header压缩

Header中含有很多固定字段,比如CookieUser-agentAccept等,这些字段加起来可能高达几百个字节,所以有必要压缩;

大量的请求和响应的报文里有很多字段是重复的,所以有必要避免重复性;

ASCII编码效率低,可以改成二进制编码。

H2使用HPACK算法进行压缩Header。使用Huffman编码压缩数据,可达到50%-90%的压缩率。

2. 二进制帧

引入帧的概念,从文本格式变为二进制格式进行传输。

TCP 协议中,数据的传输单位是数据报。数据分成两大部分。头部(header) 和 实际数据部分(body)

HTTP 2.0 中,它把数据报的两大部分分成了 header frame data frame。也就是头部帧和数据体帧。帧的传输最终在流中进行,流中的帧,头部(header)帧 和 data 帧可以分为多个片段帧,例如data帧即是可以 data = data_1 + data_2 + ... + data_n

 

一张图了解HTTP协议


 

3. Stream

流代表了一个完整的 请求-响应数据交互过程。具有如下特点:

·  双向性:同一个流内,可同时发送和接受数据。

·  有序性:流中被传输的数据就是二进制帧 。帧在流上的被发送与被接收都是按照顺序进行的。

·  并行性:流中的 二进制帧 都是被并行传输的,无需按顺序等待。但却不会引起数据混乱,因为每个帧都有顺序标号。它们最终会被按照顺序标号来合并。

·  流的创建:流可以被客户端或服务器单方面建立, 使用或共享。

·  流的关闭:流也可以被任意一方关闭。

流的概念提出是为了实现多路复用,在单个连接上实现同时进行多个业务单元数据的传输。

4. 多路复用

解决了队头阻塞的问题,一个连接中可并发多个请求和响应,无需按照顺序进行响应。

l每一个帧可看做是一个学生,流可以认为是组(流标识符为帧的属性值),一个班级(一个连接)内学生被分为若干个小组,每一个小组分配不同的具体任务。

lHTTP/1.* 一次请求-响应,建立一个连接,用完关闭;每一个小组任务都需要建立一个班级,多个小组任务多个班级,1:1比例

lHTTP/1.1 Pipeling解决方式为,若干个小组任务排队串行化单线程处理,后面小组任务等待前面小组任务完成才能获得执行机会,一旦有任务处理超时等,后续任务只能被阻塞,毫无办法,这就是队头阻塞

lHTTP/2多个小组任务可同时并行(严格意义上是并发)在班级内执行。一旦某个小组任务耗时严重,但不会影响到其它小组任务正常执行

l针对一个班级资源维护要比多个班级资源维护经济多了,这也是多路复用出现的原因

帧类型

 

一张图了解HTTP协议


HTTP3.0

HTTP3.0QUIC的区别

一般来讲,Quic协议就是指HTTP3.0,将来的演进,Quic协议会更名为HTTP3.0;就像spdy协议和HTTP2.0一样。但是细分的话,Quic协议有传输层和应用层两个层的逻辑。

QUIC有哪些特性

1. 使用UDP

2. 0-RTT

Quic协议的建连完整握手流程是1-RTT,有了一次通信后,双方后续再建立连接0-rtt就可以实现。

后面单独写一篇来讲0-rtt

 

3. 连接迁移

我们都知道,一条连接的标识是四元组,但是Quic却颠覆了这一理念,使用连接ID来标识一条连接,这就允许了一条连接 的四元组可以发生变化,只要其ID不变即可。

应用于 4G-5G-Wifi之间的切换。后面我们单独写一篇连接迁移的文章。

4. 解决了传输层的队头阻塞

 

QUIC有哪些劣势

中间设备对UDP的支持不友好

运营商对UDP的支持不友好

内核对UDP的支持不友好

比较耗CPU

报文头部比较大