HTTP使用指南 | 青训营

94 阅读6分钟

HTTP

一、HTTP发展历程

1900年HTTP/0.9为了便于服务器和客户端处理,采用了纯文本格式,只运行使用GET请求。在响应请求之后会立即关闭连接。

1996年HTTP/1.0增强了0.9版本,引入了 HTTP Header(头部)的概念,传输的数据不再仅限于文本,可以解析图片音乐等,增加了响应状态码和POSTHEAD等请求方法。

1999年广泛使用HTTP/1.1,正式标准,允许持久连接,允许响应数据分块,增加了缓存管理和控制,增加了PUT、DELETE等新的方法。(问题 多个请求并发 管线化 http队头阻塞)

2015年HTTP/2,使用HPACK算法压缩头部,减少数据传输量。允许服务器主动向客户端推送数据,二进制协议可发起多个请求,使用时需要对请求加密通信。(多路复用 1条tcp链接 来通信数据)

2018年HTTP/3基于UDPQUIC协议。

二、HTTP/1.1(纯文本协议 安全问题 明文 )

基于tcp传输层,所以tcp的问题依然存在。半双工通信,请求应答模式。http默认是无状态(默认tcp不能再没有应答完成后复用tcp通道继续发送消息)

  • HTTP/1.1是可靠传输模式,基于TCP/IP协议
  • 采用应答模式,客户端主动发起请求,服务器被动回复请求;
  • HTTP是无状态的每个请求都是互相独立
  • HTTP协议的请求报文和响应报文的结构基本相同,由三部分组成。

1.内容协商

客户端和服务端进行协商,返回对应结果

客户端Header服务端Header
AcceptContent-Type我发给你的数据是什么类型
Accept-encodingContent-Encoding我发给你的数据是用什么格式压缩(gzip、deflate、br)
Accept-language根据客户端支持的语言返回(多语言)
RangeContent-Range范围请求数据

2.长连接

HTTP/1.0 性能上的一个很大的问题,那就是每发起一个请求,都要新建一次 TCP 连接(三次握手),而且是串行请求,做了无谓的 TCP 连接建立和断开,增加了通信开销。

  • TCP的连接和关闭非常耗时间,所以我们可以复用TCP创建的连接,HTTP/1.1响应中默认会增加Connection:keep-alive(必须在一次请求应答后才能复用)

3.管线化

如果只创建一条TCP连接来进行数据的收发,就会变成”串行“模式,如果某个请求过慢就会发生阻塞问题。Head-ofline blocking,Http/1.1中采用了管线化的方式,对一个域名同时发起多个长连接实现并发。默认chrome为6个。

问题在于虽然请求是并发的,但是响应依旧是按顺序的 (管道的特点就是先发送的先回来)(队头阻塞 HTTP1.1中的队头阻塞)

因为当顺序发送的请求序列中的一个请求因为某种原因被阻塞时,在后面排队的所有请求也一同被阻塞了,会招致客户端一直请求不到数据,这也就是「队头阻塞」,好比上班的路上塞车。

4.Cookie

Set-Cookie/Cookie用户第一次访问服务器的时候,服务器会写入身份标识,下次再请求的时候会携带cookie。通过Cookie可以实现有状态的会话。

5. HTTP 缓存

HTTP 缓存有两种实现方式,分别是强制缓存和协商缓存

  • 强制缓存

    • 当浏览器第一次请求访问服务器资源时,服务器会在返回这个资源的同时,在Response头部加上Cache-ControlCache-Control中设置了过期时间的大小。

    • 浏览器再次请求访问服务器中的该资源时,会先通过请求资源的时间与Cache-Control中设置的过期时间大小,来计算出该资源是否过期,如果没有过期,则使用该缓存,否则重新请求服务器。

    • 服务器再次收到请求后,会再次更新Response头部的Cache-Control

    • Cache-Control, 是一个相对时间;

    • Expires,是一个绝对时间;

    • image-20230820102912217.png

    强制缓存存在有效期,缓存器内不会向服务器发送请求。超过时间后需要去服务端验证是否是最新版本。

  • 协商缓存

    • 当强制缓存失效后,会再次向服务器发起请求,服务器需要比对客户端的缓存的文件和服务端是否一致,如果一致则返回304状态码。如果文件更新了,那么就采用返回新文件的方式。

    • 第一种:请求头部中的 If-Modified-Since 字段与响应头部中的 Last-Modified 字段实现,这两个字段的意思是:

      • 响应头部中的 Last-Modified:标示这个响应资源的最后修改时间;
      • 请求头部中的 If-Modified-Since:当资源过期了,发现响应头中具有 Last-Modified 声明,则再次发起请求的时候带上 Last-Modified 的时间,服务器收到请求后发现有 If-Modified-Since 则与被请求资源的最后修改时间进行对比(Last-Modified),如果最后修改时间较新(大),说明资源又被改过,则返回最新资源,HTTP 200 OK;如果最后修改时间较旧(小),说明资源无新修改,响应 HTTP 304 走缓存。

      第二种:请求头部中的 If-None-Match 字段与响应头部中的 ETag 字段,这两个字段的意思是:

      • 摘要算法(md5): 不同的内容摘要的结果肯定不同,长度是相同,结果会产生剧烈变化,两个相同的内容摘要的结果肯定是相同,无法通过最终的结果反推原内容。缺点:文件过大,做摘要非常消耗性能,会简单使用弱指纹,可以用last-modified + 文件长度,成为一个指纹。
      • 响应头部中 Etag:唯一标识响应资源;
      • 请求头部中的 If-None-Match:当资源过期时,浏览器发现响应头里有 Etag,则再次向服务器发起请求时,会将请求头 If-None-Match 值设置为 Etag 的值。服务器收到请求后进行比对,如果资源没有变化返回 304,如果资源变化了返回 200。

      第一种实现方式是基于时间实现的,第二种实现方式是基于一个唯一标识实现的,相对来说后者更加准确。若是服务端返回的响应头中同时有Etag和Last-Modified字段,这时,Etag的优先级更高。

      注意,协商缓存这两个字段都需要配合强制缓存中 Cache-Control 字段来使用,只有在未能命中强制缓存的时候,才能发起带有协商缓存字段的请求

http缓存.png