HTTP协议概念
HTTP 协议是无状态的,其本身也是无连接的。
- 无状态:同一个客户第二次访问同一个服务器上的页面,服务器的响应与第一次被访问时的相同。即,HTTP 服务器不会保存关于客户的任何信息。这样设计的原因是:简化了服务器设计,使服务器更容易支持大量并发的HTTP请求
因为HTTP是无状态的,但在实际工作中,常常希望能识别用户信息。所以要做到这点就可以在HTTP中使用Cookie
- 无连接:虽然HTTP使用了面向连接的TCP作为传输层的协议,但是通信的双方在交换HTTP报文之前,不需要先建立HTTP连接
HTTP的报文
HTTP 报文有两种,一种是请求报文,一种是响应报文。
HTTP 请求报文和响应报文都是由三个部分组成的。
- 开始行:用于区别是请求报文还是响应报文,在请求报文中的开始行叫做请求行,而在响应报文中的开始行叫做状态行
- 首部行:用来说明浏览器,服务器或者报文主体的一些信息
- 实体主体:在请求报文中一般都不用这个字段,而在响应报文中也可能没有这个字段
请求报文的格式:
GET /dir/index.html HTTP/1.1 {请求行包含三个字段:方法字段、URL字段和HTTP版本字段}
Host: www.xyz.edu.cn {此行是首部行的开始,这行给出主机的域名}
Connection: close {告诉服务器发送完请求的文档后就可以释放连接}
User-Agent: Mozilla/5.0 {表明用户代理是使用火狐浏览器内核}
请求报文的最后还有一个空行,这个空行不能省略,它用来划分首部与实体。
响应报文的格式:
HTTP/1.0 200 OK {状态行包含三个字段:协议版本字段,状态码和对应的状态信息}
Content-Type: text/plain
Content-Length: 137582
Expires: Thu, 05 Dec 1997 16:00:00 GMT
Last-Modified: Wed, 5 August 1996 15:55:28 GMT
Server: Apache 0.84
{实体部分是报文的主要部分,它包含所请求的对象}
<html>
<body>Hello World</body>
</html>
HTTP/1.0,HTTP/1.1 和 HTTP/2 的区别概览
1.0 | 1.1 | 2 | |
---|---|---|---|
长连接 | 规定浏览器只与服务器保持短暂连接,除非使用keep-alive参数来告知服务器端要建立一个长连接 | 默认采用持久连接 | 默认支持 |
浏览器缓存 | 强缓存expired、协商缓存last-modified\if-modified-since 有一定的缺陷 | 增加了强缓存cache-control、协商缓存etag\if-none-match 是对http/1 缓存的优化 | ✔️ |
HOST 域 | ❌ | ✔️ | ✔️ |
多路复用 | ❌ | ❌ | ✔️ |
头部压缩 | ❌ | ❌ | 使用HAPCK算法对header数据进行压缩,使数据体积变小,传输更快 |
服务器推送 | ❌ | ❌ | ✔️ |
一些详细的解释:
- 长连接:http1.1默认保持长连接,数据传输完成保持tcp连接不断开,继续用这个通道传输数据
- 浏览器缓存:Expires控制缓存的原理是使用客户端的时间与服务端返回的时间做对比,但是客户端与服务端时区不同,那么强制缓存则会直接失效,这样的话强制缓存的存在则毫无意义。所以在HTTP/1.1中,新增Cache-Control,Cache-Control是一个绝对值,所以就不会因为时区出错。
- HOST域:举个栗子,有一台 ip 地址为 61.135.169.125 的服务器,在这台服务器上部署着谷歌、百度、淘宝的网站。为什么我们访问 https://www.google.com 时,看到的是 Google 的首页而不是百度或者淘宝的首页?原因就是 Host 请求头决定着访问哪个虚拟主机。
- 多路复用:虽然1.1中多个请求可以复用同一个TCP连接,但是同一个TCP连接里,数据请求次序是固定的。服务器只有处理完一个请求的响应后,才会进行下一个处理,所以如果前面请求的响应特别慢,就会造成许多请求排队等待,这种情况被称为队头阻塞。但HTTP/2 是一个二进制协议,可以分为头信息帧和数据帧。 帧的概念是它实现多路复用的基础。HTTP/2 仍然复用 TCP 连接,但是在一个连接里,客户端和服务器都可以同时发送多个请求或回 应,而且不用按照顺序一一发送,这样就避免了"队头堵塞"的问题。因为HTTP/2能多路复用,所以雪碧图这种优化就可以不用了。
- 头部压缩:HPACK算法是新引入HTTP/2的一个算法,用于对HTTP头部做压缩。
- 服务器推送:网站为了使请求数减少,通常采用对页面上的图片、脚本进行极简化处理。但是,这一举措十分不方便,也不高效,依然需要诸多HTTP链接来加载页面和页面资源。
HTTP/2引入了服务器推送,即服务端向客户端发送比客户端请求更多的数据。这允许服务器直接提供浏览器渲染页面所需资源,而无须浏览器在收到、解析页面后再提起一轮请求,节
约了加载时间。
HTTP1.0
- 仅支持保持短暂的TCP链接,如果要长连接则需要设置keep-alive参数指定
- 强缓存expired、协商缓存last-modified\if-modified-since 有一定的缺陷
HTTP1.1
默认长连接(keep-alive)
http请求可以复用Tcp连接,但是同一时间只能对应一个http请求(即:http请求在一个tcp中是串行的)
增加了缓存字段
强缓存cache-control、协商缓存etag\if-none-match 是对http/1 缓存的优化
管道化
基于上面长连接的基础,管道化可以不等第一个请求响应继续发送后面的请求,但响应的顺序还是按照请求的顺序返回
- 没有管道化的请求:
请求1 > 响应1 --> 请求2 > 响应2 --> 请求3 > 响应3
- 管道化的请求响应
请求1 --> 请求2 --> 请求3 > 响应1 --> 响应2 --> 响应3
断点传输
在上传/下载资源时,如果资源过大,将其分割为多个部分,分别上传/下载,如果遇到网络故障,可以从已经上传/下载好的地方继续请求,不用从头开始,提高效率
HTTP/2
二进制格式编码分帧传输
将所有传输的信息分割为更小的消息和帧,并对它们采用二进制格式的编码。
多路复用
基于二进制分帧,在同一域名下所有访问都是从同一个tcp连接中走,http消息被分解为独立的帧,乱序发送,服务端根据标识符和首部将消息重新组装起来。
头部压缩
HTTP1.x的header带有大量信息,而且每次都要重复发送,HTTP2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。
服务器推送
当我们对支持HTTP2.0的web server请求数据的时候,服务器会顺便把一些客户端需要的资源一起推送到客户端,免得客户端再次创建连接发送请求到服务器端获取。这种方式非常合适加载静态资源。
HTTP/3
虽然 HTTP/2 解决了很多之前旧版本的问题,但是它还是存在一个巨大的问题,主要是底层支撑的 TCP 协议造成的。因为在出现丢包的情况下,整个 TCP 都要开始等待重传,也就导致了后面的所有数据都被阻塞了。但是对于 HTTP/1.1 来说,可以开启多个 TCP 连接,出现这种情况反到只会影响其中一个连接,剩余的 TCP 连接还可以正常传输数据。
基于这个原因,Google 就更起炉灶搞了一个基于 UDP 协议的 QUIC 协议,并且使用在了 HTTP/3 上,HTTP/3 之前名为 HTTP-over-QUIC,从这个名字中我们也可以发现,HTTP/3 最大的改造就是使用了 QUIC。
即:HTTP/3 是基于UDP实现的
网友评论