HTTP协议发展简史小记


要说当今网络世界使用最广泛的应用协议,http绝对是最有力的竞争者,看看我们的周围吧,不管是在桌面WEB上搜索网页,还是各种移动端app里的浏览点击,都离不开http的身影。从实际数据上来看,根据某运营商出口流量统计,http流量占比在30%左右!
那么作为一名开发者,大部分程序员或多或少都需要与http打交道,如果你是一个前端,免不了要向后端发起http请求获取网页内容,如果你是一个后端研发,在REST API接口规范盛行的今天,你很难离得开编写http接口。但是我们大部分人真的了解http吗?至少对于我而言,虽然一直也在项目中使用,也看过各种关于http的书籍和文章,但似乎总是缺少系统的了解,今天尝试着写一篇文章总结一下,算是加深自己的理解吧~

1. HTTP初印象

如果你要让我不准备然后脱口而出对于HTTP的了解,那我想我大概只能说出下面的这些:

  • 应用层协议
  • 底层基于TCP
  • 无状态
  • 一请求一应答的工作方式
  • GET/POST/PUT/DELETE/OPTIONS的请求类型
  • HEADER头部可以携带一些诸如UserAgent、ContentType之类的信息
  • 安全加密使用HTTPS

基本上也就这些了,但这其实是大部分人可以说上来的,要想聊http这个话题聊的与众不同,显然这些是不够的,那就先来一段http的发展简史吧~~

2. HTTP发展历程

2.1 HTTP的诞生

可以说HTTP协议是伴随着互联网一起诞生的,因为人们设计HTTP最初的目的就是为了提供一种发布和接收HTML页面的方法。1989年,互联网之父蒂姆·伯纳斯-李在欧洲核子研究组织发起该提议,之后该标准的制定就由万维网协会(World Wide Web Consortium,W3C)和互联网工程任务组(Internet Engineering Task Force,IETF)来负责,先后发布了一系列的RFC。

2.2 HTTP/1.1

为什么要跳过前面的若干版本(主要是0.9/1.0)直接来到HTTP/1.1呢,因为早期的HTTP协议十分简陋,比如只支持GET一种请求类型,不支持头部信息,每个请求都要建立一次TCP连接等等,现在听起来问题很多,那为什么还能被挑剔的开发者忍耐10年之久呢?归根结底还是业务上没有产生迫切的需求,早期的网站基本上都是服务端渲染好HTML页面传给前端,每个页面上需要额外加载的资源很少,因此大家也没觉得有十分的必要来修改底层协议。直到随着互联网业务的快速发展,页面上要加载的内容越来越多,比如门户类网站的各种图片,为了让页面更美观的各种样式文件等等,终于人们发现现有的协议已经越来越无法满足自己的需要,有些巨头其实已经各自想了一些各种各样的办法来绕过这些问题。直到1999年公布的 RFC 2616,定义了HTTP协议中现今广泛使用的一个版本HTTP 1.1,甚至现如今的互联网上已近很难再觅到1.0版本的踪影了~~
那简单来总结一下http1.1版本的一些主要改进吧:

默认开启长连接

通过默认开启keep-alive属性,避免每次请求都要新建tcp连接的问题;虽然keep-alive属性在1.0版本里已经支持,但是需要用户自己设置开启。因为这个对页面加载性能的影响如此之大,因此也将其作为了1.1版本的一个主要改进。

支持断点续传

1.0版本每次只能从头开始读取,但是1.1版本可以在发送请求的时候在报文头里指定RANGE:bytes=xxx来通知服务端从xxx位置开始读取,从而实现了断点续传的功能。

支持host域

1.0版本只能通过IP地址来区分不同的站点,但随着后端虚拟主机(LVS)技术的发展,一台物理服务器上可以存在多个虚拟主机,这些虚拟机主机共享同一个IP地址。HTTP1.1在头部中增加了host请求头字段后,浏览器即可以通过使用host来明确表示访问服务器的哪个站点。

缓存处理

1.1版本引入了更多的缓存控制策略,比如Entity tag,if-match等,取代了原来Expires作为缓存判断的标准。

2.3 HTTP/2

互联网在发展,技术在进步,随着前后端分离架构的盛行,页面上需要加载大量的数据请求,且很多请求来自不同的数据源,用户对于页面加载的速度也要求越来越高,HTTP1.1在性能上似乎还是无法满足人们的需求,其中很重要的一个原因是队首阻塞问题没有得到根本性的解决,尽管后来人们提出了pipeline的方案试图解决这个问题,但是由于该方案实现的复杂性导致并未得到广泛的应用。
HTTP/2 由互联网工程任务组(IETF)的 Hypertext Transfer Protocol Bis(httpbis)工作小组进行开发。该组织于2014年12月将HTTP/2标准提议递交至IESG进行讨论,于2015年2月17日被批准。HTTP/2标准于2015年5月以RFC 7540正式发表。

多路复用

HTTP1.1的版本如果想并发的发送多个请求,只能是新建多个TCP连接,但是浏览器对同一个域名tcp的连接数是有限制的,不同的浏览器可能不太一样,一般是4~10个。因此对于页面同时有多个请求需要加载的情况,其它请求只能处于pending状态,等待上面的请求处理完成,如下图:
在这里插入图片描述
那为什么http/2就能够支持多路复用呢?归根结底是因为数据通道传递的最小单位不再是请求,而是拆分成了更小粒度的帧。一个消息由一个或多个帧组成,且多个帧可以乱序发送,每个帧的首部都有一个标识标记属于哪条流,这要在接收到之后就可以重新组装。借助这个概念,http/2就实现了真正意义上的多流并行,即同域名下的所有通信可以在一个连接上完成。感觉就像是本应该由传输层做的事情由应用层协议来做了~~
这种实现特别适合于多个数据量比较小的请求,比如发送1000个1k左右的请求肯定要比之前http1.1的实现性能提升很多,但是对于10个100k的请求,则优势未必那么明显了,甚至有可能会更慢,原因在于只要一帧消息出现丢包重传的情况,那么整条消息都需要重新发送,考虑到重传的性能损耗,那么性能下降也是有可能发生的。这是基于tcp的实现无法避免的。

头部压缩

为了满足各种各样的需求,人们不断的往http头部消息里塞内容,导致http头部本身的大小越来越大,甚至在很多情况下超过了body本身的大小,而http1.1每次发送请求都需要带着头部消息,大部分时候头部消息时固定不变的,这就造成了很多冗余。http/2的实现则采用HPACK对http的头部进行压缩传输,该压缩算法本质上是使用字典编码,具体的实现可参考链接。因为使用的是字典编码,因此肯定是请求数越多,效果越好,这样的话,之前在http1.1场景下为了优化性能采用的资源合并、散列域名等方式在使用http/2的时候就不是那么可取了~~

服务端推送

在http/2协议之前,假设我们访问一个index.html页面,该页面包含了一些js脚本和css样式文件,那么浏览器在解析该页面的时候就会向服务器端发起请求获取这些静态文件,请求这些文件自然带来了额外的时间开销。那么在http/2协议中推出了服务端推送功能之后,只要你在服务器端开启了该功能,就可以做到在请求index.html的时候,服务端主动给你把里面相关的静态文件推送过来,省下了再次请求的时间。当然客户端有权拒绝接受推送,只需发送RST_STREAM帧给服务器端即可;另外,这个推送也不是想推谁就推谁,它也需要遵循同源策略。

可以做个小实验,找一个支持http/2的网站,比如nghttp2,然后利用nghttp客户端工具执行:nghttp -ans https://nghttp2.org/,如下图,显示结果中带*的资源即是服务端主动推送过来的。

在这里插入图片描述

2.4 HTTP/3

随着移动互联网的快速发展,用户对APP响应时延的要求越来越高,但似乎基于tcp的http协议又有点儿无能为力了,三次握手消耗的1.5RTT,加上TLS安全传输的话,可能会有3~4个RTT连接,尽快多个请求可以复用一个连接,但TCP协议对于传输可靠性的要求导致依然无法从根本上解决队头阻塞的问题。于是人们开始将视野转向之前不太受重视的UDP,谷歌在2013年左右推出了基于UDP的QUIC协议(Quick UDP Internet Connection),而HTTP/3就是基于QUIC的HTTP协议的改进。因此HTTP/3的优点基本上都是使用QUIC带来的,这部分内容比较复杂,我挑一些重要的点说明一下吧。

2.4.1 更少的RTT

首先基于UDP的实现,减少了三次握手的1.5次RTT,其次基于DH加密算法的实现,帮助其可以使用0~1次的RTT即可建立安全的连接。关于这部分的详细实现可以参考文章

2.4.2 connectionID

之前的http协议由四元组来标识一个唯一的连接,因此当网络发生切换时,必须要重新建立一次连接,这个过程往往会需要几百毫秒的时间。为了解决这个问题,QUIC使用connectionID(一个64位随机数)来标识一个连接,即使网络连接的IP和端口发生变化,只要connectionID不变,连接依然可以维持。

2.4.3 解决队头阻塞问题

因为TCP协议处理报文是有严格的先后顺序的,因此即使http/2使用了多路复用技术,一条流上可以传不同请求的帧,但只要这条流上有报文丢失,就会出现重传,导致即使接收端收到了其他的流,也需要阻塞等待重传完成后才能复原。
而QUIC则以Packet为最小传输单元,整个加解密也是基于Packet,避免TLS的队头阻塞;另外,UDP的使用即使丢失一个报文,也不会阻塞整个连接;在此之外,通过使用FEC前向纠错码,即使一个报文发生错误,也可以通过纠错码进行纠错,不需要再次重传。

总结

最后,附上一个关于当前互联网上关于http协议使用情况的一个统计网站 , 其中可以看到使用http/2的占比已经接近70%,http/3的占比约为12%,且还在持续增长。

在这里插入图片描述

在这里插入图片描述

参考资料

  1. 如何优雅的谈论HTTP/1.0/1.1/2.0
  2. 知乎-一文读懂HTTP/2特性
  3. HTTP/2头部压缩技术
  4. 什么是Server Push
  5. 知乎-HTTP/3原理实战
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

普普通通程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值