HTTP
HTTP 的特点
- 灵活
- 请求-响应
- 传输可靠
- 无状态
HTTP 的发展
HTTP 最初的版本为 0.9,仅定义了建立 TCP 连接后,客户端向服务端请求的资源,进行支持 GET 方法;
HTTP 1.0 版本初步定义了传输规则:增加了 POST、HEAD 方法,增加了 Header 头,定义了状态码且支持任意格式数据
HTTP 1.1 版本除了完善传输规则并增加了 持久连接、管道机制、缓存控制、断点续传、虚拟网络 等特性
目前 1.1 版本也是主要使用的版本,由于 HTTP 的数据为明文传输,存在安全隐患,因而发展出了 HTTPS 协议,通过证书确保通信双方可信,传输时对数据加密避免被第三方接持
HTTP 2 优化了通信效率,对数据头部进行压缩,实现了多路复用减少请求连接
HTTP 1.x
报文格式
- 请求报文:请求行(方法 地址 协议) - 通用信息头 - 请求头 - 实体头(空行) - 报文主体
- 响应报文:状态行(协议 状态) - 通用信息头 - 响应头 - 实体头(空行) - 报文主体
请求方法包括(其中 GET、HEAD、OPTIONS、TRACE、DELETE、PUT 是幂等请求)(幂等性指一或多次请求某资源应具有同样的副作用)
- GET: 请求获取指定资源
- POST: 请求提交数据进行处理
- PUT: 请求提交数据进行替换 (整体替换)
- PATCH: 请求提交数据进行替换 (部分替换) (与 PUT 类似,但由于是部分替换,因而不被认为是幂等的)
- DELETE: 请求删除指定资源
- OPTIONS: 用于获取服务端支持的请求方法
- HEAD: 请求获取资源的响应消息头
- TRACE: 请求服务器回送收到的请求信息,主要用于测试或诊断
- CONNECT: 建立连接隧道,用于代理服务器
状态码由三位数字组成,其首位代表状态类别
- 1xx:消息类状态,如:100-客户端应该继续发送请求,102-处理将被继续执行
- 2xx:成功类状态,如:200-成功
- 3xx:重定向状态,如:301-永久重定向,302-临时重定向,304-命中协商缓存,305-指定访问代理
- 4xx:客户端错误,如:400-请求语法错误,401-用户未认证,403-请求被拒绝,404-资源不存在,405-请求方法错误
- 5xx:服务端错误,如:500-服务器异常,502-网关错误,503-服务器维护或过载,504-网关超时,505-HTTP 版本不支持
传输特性
- 持久连接:TCP 连接不关闭,可以被多个请求复用
- 默认状态下所有连接都是持久连接
- 可通过
Connection: Keep-Alive或Connection: close指定开启或关闭
- 管道机制:在一个 TCP 连接中,可以同时发送多个请求,发送过程中不需先等待服务端响应
- 依赖于持久连接
- 由于未收到响应就可以继续发生请求,所以只支持幂等请求
- 需要服务端也支持管道化,还可能导致对头阻塞问题,浏览器默认关闭管道化
- 断点续传:通过设置请求头中的 Range 字段进行实现
- 虚拟网络:同一服务器上支持多个共享同一 IP 的虚拟主机
- 缓存控制:优化了缓存标识的判断规则
存在问题
- 明文传输:无法确保传输的安全性
- 性能浪费:持久链接会占用服务端带来更大的服务器压力
- 队头阻塞:请求管道化带来的新问题,多个有序请求可能因对头受阻导致整列数据受阻。
- 独立的消息数据在一个链路上传输
- 队列上传输的数据又严格的顺序约束
- 当一列的第一个数据包(队头)受阻而导致整列数据包受阻
队头阻塞的处理
- HTTP 1.x 默认关闭管道化
- HTTP 1.x 使用并发连接(Chrome 默认 6 个)和域名分片(根据二级域名划分业务提高最大并发)提高请求效率
- HTTP 2 中引入 二进制分针和多路复用 处理
HTTPS
HTTPS = HTTP + SSL/TLS,即对传输信息进行了加密
附:SSL-安全套接层,TLS-传输层安全(1.2 以上安全),主流的版本配置为 TLS1.2 + SSL3.3
HTTP 为明文传递,存在以下问题
- 窃听风险:第三方可以获取通信内容
- 篡改风险:第三方可以修改通信内容
- 冒充风险:第三方可以冒充参与通信
SSL/TLS 协议进行了以下处理
- 信息加密,确保第三方无法窃听
- 信息校验,确保识别被篡改信息
- 配备证书,防止第三方身份冒充
加密方式
对称加密:加密解密使用同一个密钥
- 优点:加密解密效率高
- 缺点:密钥可以被窃取
非对称加密:客户端使用公钥加密,服务端使用私钥解密
- 优点:私钥无法被窃取
- 缺点:加密解密效率低
工作流程
公钥加密:客户端先向服务端索要公钥,然后用公钥加密信息,服务端收到密文后使用私钥解密
- 公钥存放在证书中,只要证书可信,公钥则可信
- 对称加密,减少加密运算消耗时间
协议过程(步骤 1 和 2 为握手阶段)
- 客户端向服务端索要并验证公钥
- 客户端与服务端协商生成对话密钥
- 客户端与服务端采用对话密钥加密通信
握手阶段(通信为明文传输)
- 客户端向服务端发出加密通信请求,ClientHello 请求
- 协议版本
- 客户端生成的随机数
- 支持的加密方法
- 支持的压缩方法
- 服务端接收请求后向客户端回应,ServerHello 响应
- 确认使用的协议版本(若与客户端不一致,服务端关闭加密通信)
- 服务端生成的随机数
- 确认使用的加密方法
- 服务器证书
- 客户端收到响应后验证证书并获取公钥,随后向服务器发送请求
- 随机数(又称 pre-master key),用于服务器公钥加密,防止被窃听
- 编码通知,决定加密方法和密钥
- 客户端握手结束通知,其值为之前内容的 hash 值,供服务端校验
- 服务端接收到请求后,根据上述三个随机数生成会话密钥,之后发送
- 编码通知
- 服务端握手结束通知,值为内容 hash,共客户端校验
流程梳理
- 客户端 -- client hello --> 服务端
- 服务端 -- 证书(公钥) --> 客户端
- 客户端(获取证书公钥) -- 公钥加密信息 --> 服务端
- 服务端(私钥解密信息) -- 生成会话密钥 --> 客户端
- 后续服务端与客户端使用会话密钥进行加密解密通信(对称加密)
HTTP 2
HTTP 2 进一步优化了通信性能,并解决了 1.1 中队头阻塞等问题
- 二进制分帧:引入头信息帧和数据帧
- 请求优先级:可以设置数据帧优先级,优化处理顺序
- 多路复用:用于解决队头阻塞问题
- 头部压缩:用于优化 Header 信息占比过重的请求 (
HPACK算法) - 服务端推送:允许服务端主动向客户端推送
二进制分帧
帧:报文被拆分为二进制帧,帧作为最小通信单位,承载特定类型的数据(Header 帧、Data 帧)
消息:HTTP 消息(请求、响应)由一个或多个帧组成
流:存在于连接中的一个虚拟通道。流可以承载双向消息,每个流都有一个唯一的整数 ID。
对于相同 Stream ID 帧是有序传输的
对于不同 Stream ID 帧是无序传输的
接收到二进制帧后将对相同 Stream ID 的帧进行组装
帧中包含着优先级、流量控制等信息,便于优化处理效率
头部压缩
采用HPACK算法进行压缩,主要包括
- 常用头信息规则映射
- 哈弗曼编码压缩数据
多路复用
可以使用单一 TCP 连接发送多个请求,数据流以消息形式发送,消息由帧组成,帧首部添加了流标识,可以无序发送,由接收方组装,从而解决 1.1 中队头阻塞的问题。
服务端推送
服务端可以在接收客户端请求后,主动推送其他资源,客户端后续发送请求时若存在相关资源则可以直接通过缓存读取