HTTP方法:

  • Get:获取资源;
  • Post:传输实体的主体;
  • Put:传输文件(需要在请求报文主体中包含文件内容,例如content-Type:text/html等信息);
  • Delete:删除文件;
  • Head:确定URI的有效性及资源更新的日期时间等;
  • Options:询问支持的方法;
  • Trace:追踪路径;
  • Connect:要求用隧道协议(SSL/TLS)连接代理。

put与post请求的区别?(北森云计算一面)

关键点:幂等性:
二者都可以创建或者更新请求;但是当两个请求相同时
  • put方法如果两个请求相同,后一个请求会把前一个请求覆盖掉,始终产生相同的结果;
  • post方法如果两个请求相同,会创建多个相同的资源。



HTTP状态码:

2XX:表示请求被正常处理了

  • 204(No Content):请求处理成功,但是没有资源返回,同时浏览器显示的页面不发生更新(例如:使用put方法上传文件的时候,如果该文件已经在服务器上,返回响应204;或者使用delete方法删除文件的时候,如果该文件已经从服务器中删除,返回响应204);
  • 206(Partial Content):范围请求,使用content-range指定资源的byte范围的时候,会响应206作为响应状态码;当服务端无法响应范围请求则返回200状态码。

3XX:表示重定向

  • 301(Moved Permanently):永久性重定向(例如:用户把URI保存为书签);
  • 302(Found):临时重定向;
  • 304(Not Modified):资源已找到,但是未符合请求附加的条件(请求报文包含:If-Modified-Since 、If-None-Match)。

4XX:表示客户端错误

  • 401(Unauthorized):认证,第一次返回需要认证,第二次返回表示用户认证失败;
  • 403(Forbidden):权限,不允许访问这个资源;
  • 404(Not Found):资源,表示服务器上没有请求的资源

5XX:表示服务器错误




HTTP缓存技术

将请求的得到的【请求 -  响应】数据缓存到本地,下次直接读取,不必在通过网络获取服务器的响应

强制缓存

  • 强制缓存指的是只要浏览器判断缓存没有过期,则直接使用浏览器的本地缓存,决定是否使用缓存的主动性在于浏览器这边。
  • 例如:status code 中标识 from disk cache 就是使用了强制缓存

利用HTTP响应头部(Response Header)字段实现

  • Cache-Control:相对时间
  • Expires:绝对时间
  • Cache-Control 的优先级高于 Expires

具体实现流程

  • 当浏览器第一次请求访问服务器资源时,服务器会在返回这个资源的同时,在 Response 头部加上 Cache-Control,设置了过期时间大小;
  • 浏览器再次请求访问服务器中的该资源时,会先通过请求资源时间 与 Cache-Control 中设置的过期时间大小,来计算该资源是否过期,如果没有过期则使用缓存,否则就重新请求服务器;
  • 服务器再次收到请求后,会再次更新 Response 头部的 Cache-Control

协商缓存

  • 通常通过服务端告知客户端是否可以使用缓存的方式,响应码为 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 字段
  • 响应头部中 Etag:唯一标识响应资源
  • 请求头部中的 If-None-Match:当资源过期时,浏览器发现响应头里有 ETag,则再次请求服务器,会将请求头 If-None-Match 值设置为 ETag 的值。服务器收到请求后进行比对,如果资源没有变化返回 304,如果资源变化了返回 200

对比:

  • 【If-Modified-Since,Last-Modified】请求响应字段,基于时间实现的
  • 【If-None-Match, ETag】请求响应字段,基于一个唯一标识实现的,能够更加准确的判断文件内容是否被修改,避免由于时间篡改导致的不可靠问题
  • 同时拥有两个字段的时候,ETag 的优先级更高
  • 协商缓存需要强制缓存中的 Cache-Control 字段配合使用,只有未能命中强制缓存的时候,才会发起带有协商缓存字段的请求

总结

  1. 浏览器请求,如果 Response 有 Cache-Control 字段说明有强制缓存,会判断资源是否过期
  2. 如果过期,会查看 Response 有 ETag 字段说明有协商缓存,向服务器请求携带 If-None-Match 字段
  3. 紧接着查看 Response 有 Last-Modified 字段说明有协商缓存,小奶狗服务器请求携带 If-Modified-Since 字段
  4. 会根据 ETag 查看文件内容是否被修改,根据 Last-Modified 与资源最近一次修改的时间比较,如果没有改动,返回 HTTP 304,从缓存中读取
  5. 如果有改动,返回HTTP 200






HTTP1.0

HTTP协议基于TCP/IP,使用了请求-应答的通信模式。

请求报文:

包含:请求方法、请求URI、协议版本、请求首部字段、内容实体;

响应报文:

包含:协议版本、状态码、状态码的原因短句、响应首部字段、主体;

优点:简单、灵活和易于拓展、应用广泛和跨平台性。
缺点:
  • 无状态协议(http1.1使用cookie解决):协议对发送过的请求或响应都不做持久化的处理,协议自身不具备保存之前发送过的请求或响应的功能;
  • 明文传输,不安全。

明文传输导致的不安全体现在?

  • 窃听风险:通信使用明文,内容可能被窃听(混合加密、SSL/TLS加密解决
  • 冒充风险:不验证通信方的身份,因此可能遭遇伪装(将公钥放到数字证书中同时利用公钥验证数字证书是否可信
  • 篡改风险:无法证明报文的完整性,所以可能被篡改(通过摘要算法生成唯一的指纹比较


HTTP1.1

持久连接:

  • 概念:减少了TCP连接的重复建立和断开所造成的额外开销,减少了服务端的负载。(也就是第一次通信需要建立连接、以后的通信直接请求和响应、不需要重复建立和断开);
  • 实现方式:HTTP1.1默认支持、HTTP1.0使用keep-alive支持。

管线化(基于持久连接):

  • 概念:在同一个TCP连接里面,客户端可以发送多个请求,只要第一个发送出去了,不必等其响应回来,就可以发送第二个请求,可以减少整体的响应时间;
  • 问题:队头阻塞,当顺序发送的请求序列中的一个请求因为某种原因被阻塞的时候,在后面排队的所有请求也一同被阻塞,会导致客户端一直请求不到数据。

cookie(保存状态)

流程:
  • 第一次,客户端发送请求报文,服务端生成cookie的信息在set-cookie : sid = xxx字段返回;
  • 客户端保存cookie信息,第二次客户端发送请求报文中携带cookie的信息,服务端检查cookie快速响应;

HTTP2.0

头部压缩
  • 如果同时发送多个请求,他们头部是一样的或者相似的,那么协议会帮你消除重复的部分;可以通过 HPACK 算法,客户端和服务端同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送相同字段了,只发送索引号,这样就可以提高速度了

二进制格式
  • 全面采用了二进制格式,头信息和数据体都是二进制(Headers Frame、Data Frame)

数据流(Stream)
  • 数据包不是按顺序发送的,同一个连接里面连续的数据可能属于不同的回应;
  • 每个请求或者响应的所有数据包,称为一个数据流;每个数据流都标识一个独一无二的编号(Stream ID), 不同的 Stream 帧可以乱序发送的,因此可以并发不同的 Stream ,因为每个帧的头部会携带 Stream ID信息,所以接收端可以通过 Stream ID 有序组装成 HTTP 消息。 而同一个 Stream 内部的帧必须时严格有序的
  • 客户端和服务端双方都可以建立 Stream,客户端建立的Stream ID必须是奇数号,服务端建立的 Stream ID 必须是偶数号
  • 客户端可以指定数据流的优先级。优先级高的请求,服务器就先响应该请求

多路复用
  • 一个TCP连接中并发多个请求或者响应,而不用按照顺序一一对应
  • 管道化实现了长连接,解决了客户端的对头阻塞;
  • 多路复用,通过Stream的并发能力,解决了服务端的对头阻塞,会将处理好的部分先返回,接着回应其他请求,再继续处理剩下的部分

服务器推送
  • 服务端不再是被动的响应,可以主动向客户端发送消息
  • 会先发送 PUSH PROMISE 帧,会告诉客户端接下来在哪个 Stream 发送资源,然后用偶数号 Stream 发送资源给客户端

总结

  • HTTP2.0 多路复用通过数据流的形式,一个 TCP 连接中可以并发多个请求或者响应,而不是按照顺序发送的,解决了对头阻塞问题;
  • 也就是说实现100个并发 Stream 时,只需要建立一个 TCP 连接;而 HTTP1.1 需要建立 100 个 TCP 连接,每个 TCP 连接都需要经过 TCP握手、慢启动、TLS握手等过程 

问题

  • HTTP2.0是基于 TCP 协议来传输数据,TCP 是字节流协议,TCP 层必须保证收到的字节数据是完整且连续的,这样内核才会将缓冲区里面的数据返回给HTTP应用;由于多个请求复用一个TCP连接,一旦发生丢包,就会触发TCP的重传机制,一个TCP连接中的所有HTTP请求都必须等待这个丢了的包被重传回来。也就是阻塞了所有的HTTP请求。

网络迁移需要重新连接?

  • 一个TCP 连接是由四元组(原IP地址、源端口、目标IP地址、目标端口)确定的,这意味着如果IP地址或者端口变动了,就会导致需要TCP 与 TLS 重新握手,不利于移动设备切换网络的场景;比如:4G网络环境却换成 WI-FI


HTTP3.0

基于QUIC 协议的实现
无对头阻塞
  • QUIC协议有类似 HTTP2.0 Stream 与 多路复用的概念,可以在同一条连接上并发传输多个Stream,每个Stream 可以认为就是一条 HTTP 请求;
  • QUIC协议会保证数据包的可靠性,每个数据包都有唯一序号唯一标识。当某个流中的一个数据包丢失了,即使流中的其他数据包到达了,数据也无法被HTTP3.0读取,需要等待重传丢失的数据 ,才会交给 HTTP3.0
  • QUIC协议连接上的 多个 Stream之间并没有依赖,都是独立的,某个流发生丢包了,只会影响该流,其他流不受影响。HTTP2.0则只要某个流中数据包丢失了,其他流也会因此受到影响,因为共用一个 TCP 连接

更快的连接建立
  • QUIC协议内部包含了 TLS1.3协议,会在自己的帧携带 TLS 里面的记录;握手的目的是 确认双方的 连接ID,连接迁移就是基于连接ID实现的

连接迁移
  • QUIC协议没有使用 四元组 的方式来绑定连接,而是通过 连接ID 来标记通信的两个端点,客户端和服务端可以各自选择一组 ID 来标记自己,因此即使移动设备的网络变化后, 导致 IP 地址变化了,只要仍保有上下文信息(比如 连接ID、TLS密钥等)就可以无缝地复用原连接,消除重连的成本,没有丝毫卡端感。


总结

  • HTTP1.1提出的管道传输解决了,客户端可以发送多个请求,不需要等待响应。但是同时也带来了问题,如果有一个请求堵塞了,那么后续的请求也统统被阻塞了。因为请求是顺序发送的,也就是造成了队头阻塞。
  • HTTP2.0提出的多路复用解决了队头阻塞,也就是多个请求复用一个TCP连接,一旦发生丢包,就会触发TCP的重传机制,一个TCP连接中的所有HTTP请求都必须等待这个丢了的包被重传回来。也就是阻塞了所有的HTTP请求。
  • HTTP3.0换成UDP解决了TCP的重传机制,同时依靠QUIC协议实现了可靠性传输。