HTTP数据传输机制的演变:从0.9到3.0

引言

对于 http 协议的认知一直都是零散的,研究了一下,于是有了这么个文章

本文一方面是介绍 http 的起源,另外一方面是关注 http 数据传输部分的技术演变并尝试去理解设计者的思路。因此,偏向于前端的功能特点会被忽略。

为什么要去了解历史进程呢?有句话叫:欲知其道,必先为史。任何一项技术必然有他的出发点,了解技术诞生的大环境,有助于更好的理解技术本身。也就是说去思考这样的问题:为什么要这样设计?有没有更好的方案?

版本号

http从0.9版本(1989年)到还未完全标准化的3.0(2018年),一共有0.9 / 1.0 / 1.1/ 2.0 / 3.0几个主要版本,下面将依次介绍。

协议萌芽

核心人物叫Tim Berners-Lee, 当时在CERN(欧洲核子研究中心)工作,CERN是一个“分布式”的研究机构,意思是研究人员分布在世界各地。所以学术交流是家常便饭,如果能有个东西能够远程分享文档那是再好不过了。

当时tcp/ip协议簇已经是主流,并且有很多基于tcp/ip协议的通信技术已经投入社会使用。因此,基于tcp协议的超文本共享便是顺理成章。

Tim构思了一个由很多节点组成的文档网络(proposal mesh),并且可以通过browser浏览这些hypertext。所谓hypertext就是不限定为普通文本,可以包含各种形式的内容(MIME)。本质上就能达成学术交流的诉求。后面Tim为了论证这个想法,自己开发了服务端以及浏览器。当这个应用被业界认可后,慢慢走向标准化,就是今天熟知的http协议。

协议诞生 - http/0.9 & http/1.0

http/0.9
这个版本上是Tim证明自己的想法而开发的原型版本,只有get方法,所谓的The One-Line Protocol,即 GET some_url。特点是:

  • response 是 html 文本
  • tcp 连接在 response 之后关闭

当然,Tim设想的http不止这些feature

http/1.0
http/0.9的问世,社会需求是认可的,但是功能还不满足一些场景应用。于是http/1.0主要是基于0.9增强了功能以适应场景需求,比如:

  • 内容协商 除了超文本,还支持其他格式
  • request-header / response-header
  • 代理
  • 缓存
  • connection 同样也是在一轮 request / response 之后关闭

这些内容都没什么特别的,因为处于我们当前视角(主流http/1.1版本)来看,反而是“减配”了

1990-1995是http/1.0的发展时段,这个领域开始风起云涌。比如网景浏览器的诞生也是在这个阶段。李彦宏工作过的infoseek也是1994年成立,两年后另外一个做搜索的项目开始启动了——google。

广泛应用 - http1.1

同样的,1.1也是基于1.0增强功能,以适应各种场景需求。关注两个点:

连接复用

  • 请求/响应默认不立即关闭,互相交换 Connection: Close之后才关闭
  • 建议每个client对一个server,最多持有2个连接rfc2616#section-8.1.4,实际上浏览器支持的是大于这个数的,浏览器的settings

被废弃的http pipeline
虽然这个技术点被废弃了,但是还是可以品味一下设计思路

HTTP 情况是,首先建立一个tcp连接,一个请求发给服务端,然后等待服务端响应,这样一个流程就完成了,这个tcp连接就承载这个轮回。这种阻塞式的交互导致有一定的“空档期”,即浪费了网络及计算资源。

为了高效利用连接,设计了一个叫http pipeline的机制:一个tcp连接可以同时支持多个请求,比如请求r1 r2 r3连续发给服务器,当服务器处理完成 响应R1 R2 R3(这里r代表request,R代表response),RFC里面描述了一句要求:

A server MUST send its responses to those requests in the
same order that the requests were received.
// 意思是服务器发送响应的时候得按照收到request的顺序。

在这里插入图片描述

为什么要有这个要求?
个人分析是因为当client收到一个response R,但是由于pipeline的原因,client无法确认这个 R是对应哪个request,因此约定一种先后顺序的队列机制。

有什么问题
由于这个机制的存在,反而约束了数据传输,并没有达到真正意义上的多路复用。比如服务端收到请求顺序如下:r1 - r2 - r3,假如r3在server内部最先处理完成,也只能等到r1 r2 处理完成并先行发送。这种情况可能会导致队头阻塞问题

改进思路
由于 client 无法给 response “对号入座”,因此可以在请求时加上一种 identifier 的机制。比如request(id: 678),服务器处理完成后,response(id: 678),这样 client 端就能对号入座了,同时也不用限定响应队列的先后关系,实际上 2.0 就是这么干的。

没有 pipeline 的情况下,为了提升资源loading效率,业界广泛利用一些 trick 来达到并行 load 资源的目的,比如 突破浏览器域名并发限制的解决方案using-multiple-tcp-connections

成功的多路复用 - http2.0

这个版本目标在于提升 PLT(page load time),这个PLT实际上就两个点,一是资源传输,二是资源解析渲染。

  • 资源解析渲染主要在于前端的优化,比如:资源渲染逻辑、语法、优先渲染可视组件等等。
  • 相对于渲染而言,数据传输还是比较卡脖子的事情,因为各种应用总是越来越复杂。

因此,还是关注数据传输。

从1.1版本的 pipeline 技术可以看出,http 的设计在打算使用多路复用。虽然因为存在一些弊端,pipeline 被抛弃了,但是大体思路是没有问题的。

http/2 在数据传输这部分是成功的一次多路复用(multiplexing)

在发送端把数据(request/response)“打碎”成Frame,在同一个 tcp connection 中传输,再在接收端把Frame重组。通过这种方式实现一个 connection 上承载多个Frame,由于 tcp connection的 Frame 可能来自于不同的 request/response,这样就实现了一个连接承载多个请求/响应。

在这里插入图片描述

图里面有几个概念

  • Stream: 一个 connection 中有多个 stream,每个 stream 有唯一 ID。stream 是个逻辑上的通信通道。
  • Message: 相当于一个 request 或 response
  • Frame: 一个 Message 包含一个或多个 Frame,Frame 就是 http2 的最小传输单元

在这里插入图片描述
正如前面如说的,请求在发送端“打碎”成 Frame,带上 stream-id m,当服务端响应时,每个 Frame 的 stream-id 均为 m,这样浏览器就能够重组,从而实现多路复用。

流量控制
基于应用层对于流量控制的需求(比如网页视频播放暂停),http/2 定义了 Flow Control。这个功能是面向 connection 或者是 stream 级别的。

这个功能类似于 tcp 的滑动窗口机制,由接收端去通知接收窗口大小

http/2 总结
通过引入 Frame + Stream 机制成功实现多路复用,这样一来

  • 一个域名下只需要一个 tcp 连接
  • 连接少了自然 TLS 握手也少了
  • 多路复用提升了网络效率
  • 应用层可控的流量控制

当然 http/2 还有其他功能,本文侧重数据传输,因此略过

大刀阔斧改革 - http3.0(http over quic)

QUIC是google研发的协议,然后提交给IETF工作组,然后标准化作为http3版本的传输协议

从前面介绍传输机制的演变过程可以看到:

  • 1.0 及之前每次通信就建立一个 connetion,用完关闭
  • 1.1 版本一方面持久化 connection 来提升性能,另外一方面尝试了多路复用( pipeline ),但由于一些弊端被弃用
  • 2.0 版本通过引入 Frame + Stream 机制成功克服了 pipeline 的弊端并实现多路复用,可以实现一个连接并发传送多个资源文件

那么http3.0如何变化?

  • 可以看到2.0已经有 Frame、flow-control 等概念,等等!这不是 tcp 的工作吗,那一定还需要 tcp 吗?
  • 在1.1推行全网的加密传输。既然加密成了“标配”,https需要握手,tcp需要握手,为什么不合并在一起?

这样看来3.0的方向就清晰了,它主要的优化方向:

  1. tcp握手 & tls握手重复多余
  2. tcp仍有HOL问题,因为2.0虽然多路复用了,但是一个资源的失败会影响其他资源的传输。
  3. 基于tcp的协议栈即使有问题也不能难以优化,涉及到网络中间设备、操作系统等,牵一发动全身

下图就是QUIC协议的结构示意
来自The QUIC Transport Protocol:Design and Internet-Scale Deployment

http/3 引入了一个新的传输层:QUIC 协议,它是基于UDP的、面向连接的、可靠的、安全的(囊括加密套件)传输协议。

QUIC传输相关的特性

  • 类似 TCP 的 ACK 、流量控制、拥堵控制等特性
  • 类似 TLS 的加密套件
  • 因为 UDP 本身没有 connection 的概念,QUIC 需要类似 TCP 的 connection 概念
  • 舍弃了 ip/port 四元组的connection,用 connection id替换,用以解决NAT-rebind
  • 为了解决HOL问题,基于http2引入了多stream的概念。流量控制可以是connection级别的也可以是stream级别的。
  • 把传输控制这个部分从传输层上移到了应用层,在工程实践中进行后续的优化、扩展、部署变得比较方便

[待细化…]

结语

  • 每一次基础技术的革新,都可能催生新的应用、新的商业机会。http的诞生也同样也引发了创业浪潮。

  • http/1.1 是基本满足需求;http/2.0 是优化传输;http/3.0 是深度定制协议;

  • http/3.0 的 QUIC 协议实际上可以单独剥离使用,比如一些 C/S 场景

  • tcp 本身设计是面向长连接优化的(比如慢启动机制),持久化连接肯定是最优解

  • 网络应用一定是倾向于更复杂的,商家都倾向于为用户提供多样性的、动态的服务。很明显,这种服务需求必然需要 load 更多的资源,比如淘宝在各个节日页面都在发生响应的变化。
    现在一定层面上都是前端技术,前端技术的弊端在于 page loading。光速是一定的,但是如何去优化传输是很重要的板块。

ref

  1. home of the first website
  2. www project history
  3. short-history-web
  4. Evolution of HTTP
  5. 欧洲核子研究中心-wikipedia
  6. rfc1945 http/1.0
  7. Introduction to HTTP/2
  8. The QUIC Transport Protocol:
    Design and Internet-Scale Deployment
  9. rfc2616-sec4
  10. HTTP/1.1-Connections rfc2616-sec8
  11. rfc2068-19.7.1 Compatibility with HTTP/1.0 Persistent Connections
  12. Hypertext document retrieval system and method
  13. infoseek-wikipedia
  14. Robin_Li-wikipedia
  15. History of the Internet
  16. History of TCP/IP
  17. Browser connection limitations
  18. undertow Http2ClientConnection.java#L397
  19. How to capture a NetLog dump
  20. netlog-viewer
  21. 《HTTP/2 in Action》
  22. 突破浏览器域名并发限制的解决方案
  23. cloudflare - The Road to QUIC
  24. chromium-quic
  25. quicwg
  26. Network Address Translation Support for QUIC
  27. 腾讯罗成-QUIC协议原理分析
  28. 让互联网更快的协议,QUIC在腾讯的实践及性能优化
  29. nginx-quic
  30. Understanding network overhead
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值