开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第4天,点击查看活动详情
HTTP1.0与HTTP1.1的区别
长连接
-
HTTP1.0默认适用短链接,客户端和服务器每进行一次HTTP交互就需要建立一次连接,任务结束就中断连接
- TCP连接的重复建立和断开造成额外开销,增加服务端的负载
- HTTP1.1默认使用长连接,只要任意一端没有明确提出断开连接,就一直保持TCP连接状态
Host域
- HTTP1.0认为每一个IP地址对应唯一一台主机,因此请求消息中的URL不传递主机名,没有host域
- HTTP1.1请求消息和响应消息都支持Host域且请求消息中如果没有Host域会报告错误400Bad Request
随着虚拟主机技术的发展,一台物理服务器上可以存在多个虚拟主机,共享一个IP地址,也就是说一个IP地址是可以对应多个域名的
比如一台IP为A的服务器上部署着谷歌、百度、淘宝的网站,在发送请求时域名解析会解析到同一个IP地址,那么如何区分用户是要具体访问主机中的哪一个应用
-
使用ip+port区分
- 需要为每个网站部署一个端口,客户端在访问的时候需要直到是哪一个端口
-
虚拟主机
- 将一台完整的服务器分成若个主机,可以在单一主机上运行多个服务,客户端就可以使用同一个ip和同一个端口号访问不同的网站,通过host域进行区分
- 通过用户请求的host域名进行区分,服务器后台解析出host域并和服务器上设置的server_name比对,如果匹配则访问,不匹配则连接丢弃报错
管道网络传输
- HTTP1.0需要收到第一个请求的回应后才可以发送第二个请求
- HTTP1.1使用长连接,使管道网络传输成为可能。在同一个TCP连接中,客户端可以发起多个请求,只要第一个请求发送出去了就可以发送第二个,不需要等待第一个请求的返回,可以减少整体的响应时间
断点续传
- HTTP1.0每次只会传输整个数据实体,没办法部分传输
- HTTP1.1默认支持断点续传,原理是在请求报文头中加入Range字段段
消息通知管理
- HTTP1.1新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源当前状态冲突;410(Gone)表示服务器上某个资源被永久性删除
缓存处理
- HTTP1.0使用header中的if-modified-since和expires作为缓存判断标准
- HTTP1.1引入了更多缓存控制策略如Entity tag,If-Unmodified-Since,If-match,If-None-Match等
节约带宽
- HTTP1.0每次只会传输整个数据实体,没办法部分传输
- HTTP1.1支持只发送header信息(不带任何body信息),如果服务器认为客户端有权限请求服务器则返回100,客户端接收到100才把body发送给服务器;如果服务器返回401,则客户端就不需要发送body了,这个机制使得无权限情况下节约了传输body的带宽
HTTP1.1和HTTP2.0的区别
头部压缩
-
HTTP1.1中Header问题
- 固定的字段占字节大
- 大量的请求和响应报文中许多字段重复
- 只对body进行压缩,没有对header进行压缩
-
HTTP2.0使用HPACK算法对header的数据进行压缩
-
HPACK算法:在客户端和服务器两端建立字典,将字段存入字典中并生成索引号,使用索引号代表字段了
-
静态字典
- 为高频出现在头部的字符串和字段建立静态表,写入HTTP/2框架中
-
动态字典
- 不在静态表范围内的头部字符串要自行构建动态表,Index从62起步,在编码解码的时候随时更新,下一次发送的时候就只需要发送一个字节的index
- 必须同一个连接上重复传输完全相同的HTTP头部
- 占用内存越来越大
-
- 哈夫曼编码压缩整数和字符串
-
二进制格式
- 二进制:体积小、速度块、没有歧义
-
HTTP2不在像HTTP1.1一样使用纯文本的报文,而是使用二进制格式,将报文分为头信息帧和数据帧
- 对人不友好,但是对计算机友好,可以直接解析二进制报文,增加了数据传输效率
- 头信息帧的最后4个字节是流标识符,最高位被保留不用,流标识位用于表示该Fream属于哪个Stream,接收方可以根据该信息从乱序的帧中找到相同Stream ID的帧从而有序组装信息
多路复用
- 为每个请求分配一个唯一的流id,并将请求分成多个块,每个块有头信息帧和数据帧组成,头信息帧中的流标识就是这个块所属请求的流id
- HTTP2不同的Stream的块是可以乱序发送的,因此可以并发不同的Stream,也就是HTTP2可以并行交错地发送请求和响应
-
流的特点
- 流是可并发的,一个HTTP2连接上可以同时发出多个流传输数据
- 客户端和服务端都可以创建流,客户端发出为奇数,服务器为偶数
- StreamID不可复用,只能顺序递增,使用完后需要发出控制帧GOAWAY关闭TCP连接
- 第0号流不能关闭,不能发送数据帧,只能发送控制帧,用于流量控制
优先级
- 客户端可以指定数据流的优先级
服务端推送
- HTTP1.1每一个网络资源都必须由客户端明确地请求
- HTTP2服务器可以主动向客户端发送消息
- 例如浏览器请求HTML时提前将可能用到的js等静态资源主动发送给客户端减少延时等待与避免请求
HTTP3.0与HTTP2.0的区别
协议
- HTTP2是基于TCP协议的
-
HTTP3将下层的TCP协议更改为UDP协议并增加了QUIC协议
-
QUIC是一个在UDP上的伪TCP+TLS+HTTP2的多路复用协议
-
Packet Header
- Long Packet Header用于首次建立连接
-
Short Packet Header用于日常传输数据
-
解决HTTP2队头阻塞问题
-
QUIC为每个流分配唯一的流ID用来表示不同的请求,同时为每个流分配一个独立的滑动窗口,使得一个连接上的多个流之间没有依赖关系,都是相互独立的
流量控制
- 通过window_update帧告诉发送方自己可以接收的字节数
- 通过BlockFrame告诉接收方由于流量控制被阻塞了,无法发送数据
- QUIC的每个Stream都有自己的滑动串口,不同Stream互相独立
-
两种级别的流量控制
-
Stream级别
- 防止单个Stream消耗连接的全部接收缓冲
- TCP的接收窗口只有在前面所有数据包都接收到了才会移动左边界
-
QUIC接收串口的左边界取决于接收到的最大偏移字节数
- 可以乱序确认
-
Connection级别
-
限制连接中所有流相加起来的总字节数,防止发送方超过连接的缓冲容量
-
-
拥塞控制
- QUIC处于应用层,不需要内核支持,更新比较快,同时还可以针对不用的应用设置不同的拥塞控制算法
-
TCP的拥塞控制需要对所有应用程序都生效,更新较慢
更快的连接建立
-
HTTP2.0中存在TCP与TLS的握手时延迟:需要经过TCP三次握手和TLS四次握手,共3个RTT时延才能发出请求数据;TCP由于拥塞控制,刚建立连接的TCP会有慢启动过程,对TCP连接产生减速效果
- TCP和TLS是分层的,分别属于内核实现的传输层、openssl库实现的表示层,难以合并在一起,需要分批次握手
-
HTTP3在传输数据前需要QUIC握手,只需要1RTT,目的是为了确认双方的连接ID;同时QUIC协议内部包含了TLS1.3,只需要1个RTT就可以以同时完成建立连接和密钥协商了
-
甚至在第二次连接时应用数据保可以和QUIC握手信息一起发送发到0RTT效果
连接迁移
- 基于TCP传输协议的HTTP协议是通过四元组确定一条TCP连接,当设备从一个网络切换到另一个网络的时候IP地址改变了,就需要断开连接重新建立连接
- QUIC没有使用四元组绑定连接,而是通过连接ID标识通信的两个端点,客户端和服务器各选择一组ID标识自己,因此即使移动设备网络变化导致IP地址变化了,只要仍然有上下文信息(连接ID、TLS密钥等)就可以无缝复用原连接了,消除重连成本
-