1 HTTP 基础

1.1 HTTP常见状态码

  • 1XX: 提示信息,表示目前是协议处理的中间状态,还需要后续的操作
  • 2XX:成功,报文已经被收到并正确处理
    • 200:成功,如果是非HEAD请求,返回响应头会有body数据
    • 204:与200基本相同,但还是响应头没有body数据
    • 206:用于HTTP分块下载或断点续传,表示返回的body不是全部资源
  • 3XX:重定向,资源位置发生变动,需要客户端重新发送请求
    • 301:永久重定向
    • 302:临时重定向
    • 304:资源未修改,重定向缓冲文件,告诉客户端可以使用缓冲资源
  • 4XX:客户端错误,请求报文有误,服务器无法处理
    • 400:请求报文有错,笼统错误
    • 403:服务器禁止访问资源
    • 404:请求资源在服务器不存在或未找到
  • 5XX:服务器错误,服务器在处理请求时内部发生了错误
    • 500:服务器发生错误,笼统错误
    • 501:客户端请求的功能不支持
    • 502:服务器作为网关或代理时返回的错误码,表示服务器自身工作正常,但是访问后端服务器发生错误
    • 503:表示服务器忙碌,展示无法响应客户端

1.2 HTTP常见字段

  • Host字段:指定服务器域名
  • Content-Length字段:表示本子回应的数据长度
  • Connection字段:常用于客户端要求服务器使用长连接
  • Content-Type字段:用于服务端响应时,告诉客户端本次数据是什么格式
  • Accept字段:客户端告诉服务器可以接受哪些数据
  • Content-Encoding字段:表示数据压缩方法
  • Accept-Encoding字段:客户端告诉服务器可以接受哪些压缩方式

1.3 GET和POST

  • 语义上:GET表示从服务器获取指定资源,POST表示根据请求负荷对指定资源作出处理
  • 安全和幂等:GET方法是安全且幂等的,浏览器可以对GET做数据缓存,也可以在代理层做缓存,GET可以被保存为书签;POST是不安全的,并且不是幂等的,浏览器也不会缓存POST请求,也不能把POST请求保存为书签。
  • 如果不按照规范开发:GET可以变为不安全且不幂等的,POST也可以变为安全和幂等的。
  • GET可以携带body数据,POST也可以在URL中携带参数

1.4 HTTP缓存技术

分为强制缓存和协商缓存两种。

  • 强制缓存
    • 浏览器判断缓存没有过期,就直接读本地缓存,主动权在浏览器
    • 使用字段:
      • Cache-Control,一个相对时间,优先级更高
      • Expires,一个绝对时间
  • 协商缓存
    • 响应码304
    • 使用字段:
      • 请求携带If-Modified-Since和响应携带Last-Modified,基于时间比较
      • 请求携带If-None-Match和响应携带Etag,基于唯一标识比较
      • Etag优先级更高
  • 强制缓存未命中才会走协商缓存

1.5 HTTP 特性

  • HTTP/1.1

    • 简单:header+body,头部信息为key-value形式
    • 灵活易于扩展:请求方法、状态码等允许开发人员自定义和扩充,工作在应用层(7层),下层可以随意变化
    • 跨平台
    • 无状态:基于Cookie和Session等方式记录操作状态
    • 明文传输,不验证双方身份,无法证明报文完整性,不安全
    • 长连接
    • 管道网络传输,不必等待上一个请求响应,可以连续发送,但是默认不开启
    • 队头阻塞:一个请求因为某些原因被阻塞时,后面排队的请求会一同被阻塞
  • HTTP/2.0做了什么优化

    • 头部压缩,如果同时发送的多个请求头部有相似内容,协议会清楚重复部分(HPACK算法:客户端和服务端同时维护一个头部信息表,生成索引号,后续发送索引号提高速度)
    • 二进制格式:头信息和数据题都是二进制,统称为帧(头信息帧和数据帧),增加了数据传输的效率。
    • 并发传输:多个Stream复用在一条TCP连接,1 个 TCP 连接包含多个 Stream,Stream 里可以包含 1 个或多个 Message,Message 对应 HTTP/1 中的请求或响应,由 HTTP 头部和包体构成。Message 里包含一条或者多个 Frame,Frame 是 HTTP/2 最小单位,以二进制压缩格式存放 HTTP/1 中的内容(头部和包体)。(针对不同的 HTTP 请求用独一无二的 Stream ID 来区分,接收端可以通过 Stream ID 有序组装成 HTTP 消息,不同 Stream 的帧是可以乱序发送的,因此可以并发不同的 Stream ,也就是 HTTP/2 可以并行交错地发送请求和响应。)
    • 服务器推送:双方都可以建立Stream。
    • HTTP/2 通过 Stream 的并发能力,解决了 HTTP/1 队头阻塞的问题,看似很完美了,但是 HTTP/2 还是存在“队头阻塞”的问题,只不过问题不是在 HTTP 这一层面,而是在 TCP 这一层。(HTTP/2 是基于 TCP 协议来传输数据的,TCP 是字节流协议,TCP 层必须保证收到的字节数据是完整且连续的,这样内核才会将缓冲区里的数据返回给 HTTP 应用,那么当「前 1 个字节数据」没有到达时,后收到的字节数据只能存放在内核缓冲区里,只有等到这 1 个字节数据到达时,HTTP/2 应用层才能从内核中拿到数据,这就是 HTTP/2 队头阻塞问题。)
  • HTTP/3

    • HTTP/1.1 中的管道( pipeline)虽然解决了请求的队头阻塞,但是没有解决响应的队头阻塞,因为服务端需要按顺序响应收到的请求,如果服务端处理某个请求消耗的时间比较长,那么只能等响应完这个请求后, 才能处理下一个请求,这属于 HTTP 层队头阻塞。
    • HTTP/2 虽然通过多个请求复用一个 TCP 连接解决了 HTTP 的队头阻塞 ,但是一旦发生丢包,就会阻塞住所有的 HTTP 请求,这属于 TCP 层队头阻塞。
    • UDP 发送是不管顺序,也不管丢包的,所以不会出现像 HTTP/2 队头阻塞的问题。大家都知道 UDP 是不可靠传输的,但基于 UDP 的 QUIC 协议 可以实现类似 TCP 的可靠性传输。

    • QUIC特点:

      • 无队头阻塞:QUIC 协议也有类似 HTTP/2 Stream 与多路复用的概念,也是可以在同一条连接上并发传输多个 Stream,Stream 可以认为就是一条 HTTP 请求。(QUIC 有自己的一套机制可以保证传输的可靠性的。当某个流发生丢包时,只会阻塞这个流,其他流不会受到影响,因此不存在队头阻塞问题。这与 HTTP/2 不同,HTTP/2 只要某个流中的数据包丢失了,其他流也会因此受影响。)

      • 更快的连接建立:HTTP/3 在传输数据前虽然需要 QUIC 协议握手,但是这个握手过程只需要 1 RTT,握手的目的是为确认双方的「连接 ID」,连接迁移就是基于连接 ID 实现的。

        但是 HTTP/3 的 QUIC 协议并不是与 TLS 分层,而是 QUIC 内部包含了 TLS,它在自己的帧会携带 TLS 里的“记录”,再加上 QUIC 使用的是 TLS/1.3,因此仅需 1 个 RTT 就可以「同时」完成建立连接与密钥协商。

      • 连接迁移:基于 TCP 传输协议的 HTTP 协议,由于是通过四元组(源 IP、源端口、目的 IP、目的端口)确定一条 TCP 连接。当移动设备的网络从 4G 切换到 WIFI 时,意味着 IP 地址变化了,那么就必须要断开连接,然后重新建立连接。而 QUIC 协议没有用四元组的方式来“绑定”连接,而是通过连接 ID 来标记通信的两个端点,客户端和服务器可以各自选择一组 ID 来标记自己,因此即使移动设备的网络变化后,导致 IP 地址变化了,只要仍保有上下文信息(比如连接 ID、TLS 密钥等),就可以“无缝”地复用原连接,消除重连的成本,没有丝毫卡顿感,达到了连接迁移的功能。

        QUIC 是一个在 UDP 之上的 TCP + TLS + HTTP/2 的多路复用的协议。

        QUIC 是新协议,对于很多网络设备,根本不知道什么是 QUIC,只会当做 UDP,这样会出现新的问题,因为有的网络设备是会丢掉 UDP 包的,而 QUIC 是基于 UDP 实现的,那么如果网络设备无法识别这个是 QUIC 包,那么就会当作 UDP包,然后被丢弃。

1.6 HTTP和HTTPS

  • HTTPS在HTTP基础上加入了SSL/TLS安全协议。
  • 默认端口HTTP是80,HTTPS是443。
  • HTTPS需要向CA(证书权威机构)申请数字证书,来保证服务器身份是可信的。
HTTP的三个风险
  1. 窃听风险
  2. 篡改风险
  3. 冒充风险
HTTP如何解决三个风险
  1. 混合加密实现信息的机密性
  2. 摘要算法保证数据的完整性
  3. 服务器公钥放入数字证书,解决了冒充的风险
混合加密

HTTPS在通信建立前,采用非对称加密交换会话密钥,后续通信过程使用对称加密。

摘要算法+数字签名

摘要算法通过哈喜欢书计算唯一哈希值,并且无法通过哈希值推导出内容,但是不能保证「内容+哈希值」不被中间人替换,因为缺少对消息是否来源于服务端的证明。

采用非对称加密:

  • 公钥加密,私钥解密:保证内容传输的安全
  • 私钥加密,公钥解密:保证消息不会被冒充

数字签名通过「私钥加密,公钥解密」的方式确认消息的身份,私钥由服务端保管,服务端向客户端办法对应的公钥。

数字证书
  1. 服务器将自己的公钥注册到CA,保证公钥可信
  2. CA用自己的私钥对服务器的公钥进行数字签名,并颁发数字证书
  3. 客户端拿到服务器的数字证书后,使用CA的公钥确认真实性
  4. 从数字证书获取服务器公钥后,使用它对报文加密后发送

1.7 HTTPS连接如何建立

基本流程:

  1. 客户端向服务器索要并验证服务器公钥
  2. 双方翻协商产生「会话密钥」
  3. 双方采用「会话密钥」进行加密通信

SSL/TLS的建立(1,2):

  1. TCP三次握手

  2. TLS四次握手(注意TLS1.3为3次握手)

    1. Client Hello:随机数C+客户端TLS版本号+密码套件列表<-ACK

    2. Server Hello:随机数S+确认TLS版本号+使用的密码套件+数字证书<-ACK

      此时客户端会计算出会话密钥(C和S和pre-master计算得出)

    3. Client Response:公钥加密的随机数pre-master+加密通信算法改变通知+之前内容的摘要

    4. Server Response:解密pre-master,计算出「会话密钥」,发送之前握手数据的摘要

  3. 对称加密通信

数字证书的校验:

  1. 签发过程
    • CA把持有者的公钥、用途、颁发者、有效时间等信息打包,计算Hash值
    • CA使用私钥对Hash值加密,生成证书签名
    • CA将证书签名加在文件证书后,形成数字证书
  2. 校验过程
    • 客户端使用同样的Hash算法计算Hash值
    • 客户端使用CA公钥解密证书签名
    • 比对解密后的Hash值和计算出的Hash值
  3. 证书链
    • 客户端拿到证书,如果本地没有保存证书,则会查看其签发者,直到GlobalSign Root CA(根证书,自签证书)
    • 随后反向拿公钥验证可信性。
    • 确保根证书的绝对安全性,将根证书隔离地越严格越好,不然根证书如果失守了,那么整个信任链都会有问题。

1.8 HTTPS的应用数据是如何保证完整性的

TLS实际上分为握手协议和记录协议

  • 握手协议:4次握手生成对称密钥的过程
  • 记录协议:负责保护应用程序数据并验证其完整性和来源
  1. 首先分片、压缩
  2. 加上消息认证码MAC值,通过Hash算法计算生成
  3. 经过对称加密货的密文
  4. 加上数据类型、版本号、压缩后长度形成报文数据

2 HTTP/1.1如何优化

主要针对队头阻塞问题进行优化

  • 尽量避免发送HTTP请求:缓存技术(强制缓存和协商缓存)
  • 需要发送HTTP请求时减少请求次数:
    • 减少重定向次数:重定向请求工作交给代理服务器,客户端不感知
    • 合并请求:将图片、js、css文件打包
    • 延迟发送请求:类似懒加载
  • 减少HTTP响应数据大小:压缩
    • 有损压缩
    • 无损压缩

3 HTTP/2优化在何处

  • 头部压缩
  • 二进制帧传输数据
  • 并发传输
  • 服务器主动推送资源

4 HTTP/3

HTTP/2仍然存在队头阻塞问题,TCP和TLS握手延迟高,网络迁移需要重新连接

HTTP3将传输协议替换成了UDP,并在应用层实现QUIC协议,是的UDP“可靠”。

  • 无队头阻塞
  • 更快的连接建立
  • 连接迁移

5 HTTP和RPC的关系

  • 服务发现:向某个服务发起请求,需要找到服务的IP和端口,HTTP协议可以通过DNS解析得到IP并采用默认端口,而RPC需要有专门的中间服务去保存服务名的IP信息和端口信息
  • 底层连接形式:HTTP采用TCP,并使用长连接进行复用连接,而基于TCP的RPC一般会维护一个连接池,但是RPC实际上也可以基于UDP实现
  • 传输内容:HTTP传输的是HTTP报文,需要遵守HTTP协议,但是RPC定制化程度很高,可以采用多种序列化方式保存结构体,性能更好
  • 实现层面:基于HTTP实现RPC可以直接采用web服务器,并且不需要额外设定协议,但是如果基于TCP去实现,需要开发客户端和服务端代码,还需要解决粘包、拆包问题等

6 HTTP和WebSocket

如果想要服务器主动向客户端推送消息:

  • 使用HTTP:前端不断轮询发送请求消息,「伪」推送(长轮询和短轮询)
  • 使用WebSocket:在HTTP协议建立基础上,发送升级协议请求,建立全双工的WebSocket通信

TCP协议本身是全双工的,但是HTTP/1.1是半双工,升级后的WebSocket和HTTP就没有关系了。