HTTP1.X、HTTP2.0、HTTP3.0
转自:https://www.soulferry.xyz/?p=704
HTTP是什么?
HyperText Transfer Protocol,超文本传输协议,是目前互联网上应用最广泛的一种网络协议,所有的www文件都必须遵守该标准。而Http
又使用了可靠的数据传输协议TCP协议,不会产生数据丢失和损坏。
什么是TCP?
计算机和网络设备相互通讯,必须满足一种规则,这种规则称之为协议。(protocal)
因为HTTP协议是属于TCP/IP协议簇的,所以先简单介绍下与HTTP相关的TCP/IP知识。
TCP/IP简介
TCP/IP是一个协议簇,是由许多协议组成的。
TCP/IP分层模型如下:
应用层 | 有各类通用的通信服务,如FTP、DNS;HTTP也在这层 |
传输层 | 提供两种性质不同的协议,TCP(http1x、http2)和UDP(http3) |
网络层 | 网络层用来处理在网络上流动的数据包,数据包是网络传输中最小的数据单位,该层规定了数据通过怎样的方式(传输路线)到达对方计算机,并把数据包传送给对方。TCP/IP协议处于该层。 |
链路层 | 用来处理链路网络的硬件部分。包括控制操作系统、硬件的设备驱动、NIC。 |
与HTTP密切关联的TCP、IP以及DNS
IP协议位于网络层,作用是把各种数据包发送给对方,通过IP地址和MAC地址来保证数据传达。
IP地址指明了节点被分配的地址,MAC地址是网卡所属的固定地址,彼此可进行配对,IP地址可变,但是MAC地址不可变。
ARP(Address Resolution Protocol)协议是一种解析地址的协议,可根据IP地址解析出对应的MAC地址。
TCP协议是如何做到可靠的数据传输的?
首先,TCP位于传输层,为了方便传输,将大块的数据进行分割以报文为单位的数据包进行管理,即所谓的字节流服务。
三次握手策略。TCP协议将数据发送出去后,一定会向对方确认数据是否送达,否则会按顺序重新发送相同的数据包。
字段 | 含义 |
URG | 紧急指针是否有效。为1,则表示需要优先处理。 |
ACK | 确认号是否有效,一般置为1。 |
PSH | 提示接收端应用程序立即从TCP缓冲区把数据读走。 |
RST | 对方需要重新建立连接,复位。 |
SYN | 请求建立连接,并在其序列号的字段进行序列号的初始值设定。建立连接,设置为1。 |
FIN | 希望断开连接。 |
三次握手流程
四次挥手流程
在HTTP1.1中,默认连接是持久连接的(http keep-alive),特点是只要任意一端没有明确断开连接,则保持tcp链接状态。这样就可以做到同时并行的发送多个请求,而不需要一个个的等待响应。
DNS(domain name system)也位于应用层的协议,它提供域名到IP地址的解析服务。
HTTP的工作流程
- 浏览器与服务器建立TCP连接,即三次握手
- TCP连接成功,浏览器发送HTTP请求命令
- 服务接收到请求并返回HTTP响应
- 服务器关闭连接,即四次挥手
- 浏览器解析请求的资源
Connection:keep-alive可以让TCP连接保持打开,浏览器可继续通过相同的连接发送请求。其实HTTP1.1所有的请求都是默认保持持续连接的
HTTP1.1
HTTP报文
http报文分为请求和响应报文。由多行(CR+LF作为换行符)数据结构构成的字符串文本,大致可以分为报文首部和报文主体。
- 请求行:包含请求方法,请求的URI和HTTP版本
- 状态行:包含响应结果的状态码
- 首部字段:包含请求和响应的各种条件、属性的各类首部;
- 其他:包含未定义的首部如Cookie等
请求格式
# 请求方法 URL 协议/版本 GET /u013870094/article/details/79098628 HTTP/1.1 # 用于指定被请求资源的Internet主机和端口号 Host: blog.csdn.net # 表示是否需要持久连接。 Connection: keep-alive # 防止页面被缓存,只有一个用法, Pragma: no-cache Pragma: no-cache # 这个用来指定Response-Request遵循的缓存机制 # Cache-Control:Public 可以被任何缓存所缓存,多用户间共享 # Cache-Control:Private 内容只缓存到私有缓存中,不能在用户间共享 # Cache-Control:no-cache 所有内容都不会被缓存 # Cache-Control: max-age=x:缓存时间 以秒为单位 Cache-Control: no-cache Upgrade-Insecure-Requests: 1 # 览器的名称和版本等信 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36 # 浏览器可以接受的媒体类型(MIME类型) Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3 # 提供了Request的上下文信息的服务器,告诉服务器我是从哪个链接过来的, Referer: https://blog.csdn.net/u013870094/article/details/79098628 # 浏览器申明自己接收的编码方法,通常指定压缩方法,是否支持压缩,支持什么压缩方法(gzip,deflate) Accept-Encoding: gzip, deflate, br # 浏览器申明自己接收的语言。 Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
响应格式
HTTP/1.1 200 OK Date: Wed, 23 Oct 2019 02:14:16 GMT Content-Type: text/html; charset=UTF-8 Transfer-Encoding: chunked Connection: keep-alive Server: openresty Vary: Accept-Encoding Content-Encoding: gzip Strict-Transport-Security: max-age=86400
浏览器缓存
- 第一次请求,浏览器通过HTTP的header报文头部,附带
Expires,Cache-Control,Last-Modified/Etag
向服务器请求,此时服务器记录第一次请求的Last-Modified/Etag
- 再次请求,附带头部信息
Expires,Cache-Control,If-Modified-Since/If-none-match
- 服务器比对两次的
Last-Modified/Etag
与If-Modified-Since/If-none-match
判断资源未发生变化,返回304响应
HTTP1.1对比HTTP1.0的优点
1.长连接
HTTP1.1支持长连接和请求的流水线处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启长连接keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。HTTP1.0需要使用keep-alive参数来告知服务器端要建立一个长连接。
2.节约带宽
HTTP1.0中存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能。HTTP1.1支持只发送header信息(不带任何body信息),如果服务器认为客户端有权限请求服务器,则返回100,客户端接收到100才开始把请求body发送到服务器;如果返回401,客户端就可以不用发送请求body了节约了带宽。
3.HOST域
在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname),HTTP1.0没有host域。随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都支持host域,且请求消息中如果没有host域会报告一个错误(400 Bad Request)。
4.缓存处理
在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。
5.错误通知管理
在HTTP1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。
HTTP1.1存在的问题
- 高延迟 — 队头阻塞(Head-Of-Line Blocking)
- 无状态特性 — 阻碍交互
- 明文传输 — 不安全性
- 不支持服务端推送
队列阻塞
队列阻塞是指当顺序发送的请求序列中的一个请求因为某种原因被阻塞时,在后面排队的所有请求也一并被阻塞,会导致客户端迟迟收不到数据。
如何解决队列阻塞?
- 将同一页面的资源分散到不同域名下,提升连接上限。虽然能公用一个 TCP 管道,但是在一个管道中同一时刻只能处理一个请求,在当前的请求没有结束之前,其他的请求只能处于阻塞状态。
- 减少请求数量
- 内联一些资源:css、base64 图片等
- 合并小文件减少资源数
无状态特性
无状态是指协议对弈连接状态没有记忆能力。单纯的HTTP是没有cookie,accept,user-agent等header信息缓存的,每一个链接都是一个新的链接。上次请求的验证信息,下次请求并不知道与上次的关联性,还是要再次携带验证参数的。因此会造成请求头过大的问题。
- 携带过多的header信息,如user-agent,cookie,accept等;
- 请求报文有过多的重复字段,资源浪费;
明文传输,不安全
传输内容没有加密,中途可能被篡改和劫持。
不支持服务推送
HTTP2.0
SPDY协议
HTTP/2是现行HTTP协议(HTTP/1.x)的替代,但它不是重写,HTTP方法/状态码/语义都与HTTP/1.x一样。HTTP/2基于SPDY,专注于性能,最大的一个目标是在用户和网站间只用一个连接(connection)。
http2.0优点
- 多路复用 — 解决队头阻塞
- 头部压缩 — 解决巨大的 HTTP 头部
- 请求优先级 — 先获取重要数据
- 服务端推送 — 填补空缺
- 提高安全性
- 二进制分帧
多路复用
- 同一个域名下的所有通信都在单个连接上完成;
- 单个连接可以承载任意数量的双向数据流;
- 数据流以消息的形式发送,而消息由一个或多个帧组成,可以乱序发送,因为根据帧首部的流标识可以重新组装。
这样做的好处在于:
- 同一个页面,只需要一个TCP慢连接的过程;
- 可以并行交错的发送请求,请求之间互不影响;
请求头信息压缩
采用HPACK算法压缩头部,压缩率50%-90%;
同时,同一个域名下的两个请求,只会发送差异数据,减少冗余的数据传输,降低开销。
请求优先级
虽然无限的并发流解决了队头阻塞的问题,但如果带宽受限,客户端可能会因防止堵塞通道而阻止请求。在网络通道被非关键资源堵塞时,高优先级的请求会被优先处理。
服务端推送
指的是服务端可以新建“流”主动向客户端发送消息,提前推送客户端需要的静态资源,减少等待的延迟。客户端也是可以拒绝接收的。
提高安全性
为了兼容,HTTP2也是明文的,只不过格式是二进制的,但HTTP2都是https协议的,跑在TSL上面。
二进制分帧
HTTP/2 将请求和响应数据分割为更小的帧,并且它们采用二进制编码。
它把TCP协议的部分特性挪到了应用层,把原来的”Header+Body”的消息”打散”为数个小片的二进制”帧”(Frame),用”HEADERS”帧存放头数据、”DATA”帧存放实体数据。HTP/2数据分帧后”Header+Body”的报文结构就完全消失了,协议看到的只是一个个的”碎片”。
HTTP/2 中,同域名下所有通信都在单个连接上完成,该连接可以承载任意数量的双向数据流。每个数据流都以消息的形式发送,而消息又由一个或多个帧组成。多个帧之间可以乱序发送,根据帧首部的流标识可以重新组装。
HTTP2.0存在缺点
- TCP 以及 TCP+TLS 建立连接的延时
- TCP 的队头阻塞并没有彻底解决
- 多路复用导致服务器压力上升
- 多路复用容易 Timeout
建立连接延时
TCP 连接需要和服务器进行三次握手,即消耗完 1.5 个 RTT 之后才能进行数据传输。
TLS 连接有两个版本—— TLS1.2 和 TLS1.3,每个版本建立连接所花的时间不同,大致需要 1~2 个 RTT。
RTT(Round-Trip Time):
往返时延。表示从发送端发送数据开始,到发送端收到来自接收端的确认(接收端收到数据后便立即发送确认),总共经历的时延。
队列阻塞没有彻底解决
TCP 为了保证可靠传输,有一个“超时重传”机制,丢失的包必须等待重传确认。HTTP2 出现丢包时,整个 TCP 都要等待重传,那么就会阻塞该 TCP 连接中的所有请求。
RTO:英文全称是 Retransmission TimeOut,即重传超时时间; RTO 是一个动态值,会根据网络的改变而改变。RTO 是根据给定连接的往返时间 RTT 计算出来的。 接收方返回的 ack 是希望收到的下一组包的序列号。
多路复用会导致服务器压力过大
多路复用没有限制同时请求的数量。请求的平均数量与往常相同,但是机会有许多请求短暂爆发,导致瞬时QPS暴增。
QPS每秒查询率(Query Per Second)。
每秒查询率QPS是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准,在 因特网上,作为 域名系统服务器的机器的性能经常用每秒查询率来衡量。对应fetches/sec,即每秒的响应请求数,也即是最大吞吐能力。
多路复用容易造成请求timeout
大批量的请求同时发送,由于 HTTP2 连接内存在多个并行的流,而网络带宽和服务器资源有限,每个流的资源会被稀释,虽然它们开始时间相差更短,但却都可能超时。
即使是使用 Nginx 这样的负载均衡器,想正确进行节流也可能很棘手。 其次,就算你向应用程序引入或调整排队机制,但一次能处理的连接也是有限的。如果对请求进行排队,还要注意在响应超时后丢弃请求,以避免浪费不必要的资源。
HTTP3.0
HTTP3.0的QUIC协议
google在推出SPDY协议之后就发现了SPDY存在的问题,于是就又开发了一个基于UDP协议的QUIC协议。这个就是HTTP3.0。他完美的解决了请求队列阻塞的问题。
HTTP3.0主要特点
- 改进的拥塞控制、可靠传输、流量控制等
- 基于UDP协议的改造,实现了快速握手
- 集成了 TLS 1.3 加密
- 多路复用,彻底解决了队列阻塞问题
- 连接迁移
改进拥塞控制、传输可靠性
从拥塞控制和可靠传输本身来看,QUIC只是按照TCP协议重新实现了一遍,QUIC协议主要改进了一下几个方面:
1.可插拔-应用程序层面就能实现不同的拥塞控制算法
一个应用程序的不同链接也能支持配置不同的拥塞控制。应用程序不需要停机和升级就能实现拥塞控制的变更,可以针对不同的业务,不同的网络制式,甚至不同的RTT,使用不同的拥塞控制算法。
2.单调递增的Packet Number -使用了Packet Number代替了TCP的SEQ
每一个Packet Number都是严格递增的,也就是说就算Packet N丢失了,重传Packet N的Packet
Number已经不是N,而是一个比N大的值。而TCP的重传策略存在二义性,比如客户端发送了一个请求,一个RTO后发出重传,而实际服务端只接受了第一次请求,并且请求已经在返回的路上了,当客户端收到相应之后,得出RTT将会比真实的RTT小。当Packet N唯一之后,就可以计算正确的RTT。
3.不允许Reneging – 一个Packet只要被ACK标记,就认为他一定被正确接收。
Reneging 的意思是,接收方有权把已经报给发送端 SACK(Selective Acknowledgment) 里的数据给丢了(如接收窗口不够而丢弃乱序的包)。
QUIC协议的ACK包含了与TCP中的ACK等价的信息,但QUIC不允许任何已被确认的数据包丢失。这样就简化了发送端与接收端的实现难度,还可以减少发送端的压力。
4.向前纠错 FEC
早期的QUIC版本存在一个丢包恢复机制,但后来增加带宽消耗并且效果一般所以被废弃。FEC中,QUIC协议的数据帧数据混合原始数据和冗余数据,来确保无论到达接收端的N次传输内容是什么,接收端都能恢复所有n个原始数据包。FEC的实质就是异域。
5.更多的ACK块和增加ACK delay时间
QUIC可以同时提供256个ACK Block,因此在重排序时,QUIC相对于TCP(使用的SACK)更具有弹性,这也使得在重排或者丢失出现时,QUIC可以在网络上保留更多地在途字节。在网络环境较差的情况下,可以提升网络的恢复速度,减少重传量。
TCP的timestamp选项存在一个问题:发送方在报文发送时设置发送时间戳,接收方在确认该报文段时把时间戳字段值复制到确认报文时间戳,但是没有计算接收端接收到包,再到发送ACK的时间。这个时间称之为ACK delay,会导致RTT计算误差。