无标题文章

  1. 背景
    这篇文档会从技术和协议层面来介绍http2。文档起源于2014年4月我在斯德哥尔摩做了一次相关的演讲,在那之后我对演讲内容的细节进行了一些解释和补充,从而写出了这篇文档。
    正式版http2规格标准叫做RFC 7540,发布于2015年5月15日:http://www.rfc- editor.org/rfc/rfc7540.txt 如果你有在这篇文章中发现任何我的失误造成的错误或疏漏,请帮我指正。我会在后续版本 中修改。
    为了让阅读体验更流畅,在这篇文章中我会使用“http2”来指代这一新协议,但请记住该协议的正式名字是HTTP/2。

  2. HTTP的现状
    当前,几乎所有互联网上的内容都采用HTTP 1.1作为通信协议。人们在该协议上投入了大量精力,因此基于该协议的基础架构得以日臻完善。得益于此,在现有的HTTP协议之上构建新的方案会比从底层建立新的协议要容易得多。
    2.1 HTTP 1.1过于庞大
    HTTP刚诞生的时候被看作一个相对简单直观的协议,但时间证明了早期的设计并不尽人意。 于1996年发布的、描述HTTP 1.0规范的RFC 1945只有60页,但仅仅3年之后,描述HTTP1.1规范的RFC 2616就骤增至176页。当我们在IETF小组对该规范进行更新时,更是被拆分成了总页数更多的六个文档(这就是RFC 7230及其文件族的由来与诞生)。总而言之,HTTP1.1包含了太多细节和可选内容,这让它变得过于庞大。
    2.2 过多的可选项
    HTTP 1.1不仅包含了非常多的细枝末节,也为未来的扩展预留了很多选项。这种事无巨细的风格导致在现有的软件生态中,几乎没有任何实际场景真正实现了协议中提及的所有细节, 甚至要弄清楚“所有细节”到底包括哪些内容都非常困难。这也导致了很多最初不常用的功能在后来的实现中得到很少支持,而有些最初实现了的功能,却又很少被使用。
    随着时间推移,当客户端和服务器开始增加对于这些功能的使用时,**互用性
    ** (interoperability)问题就暴露了出来。HTTP管线化(HTTP Pipelining)就是一个非常好的例子。
    2.3 未能被充分利用的TCP
    HTTP 1.1很难完全使用出TCP协议能提供的所有强大能力。HTTP客户端和浏览器必须要另辟蹊径,去寻找新的解决方案来降低页面载入时间。
    与此同时,人们也尝试使用新的协议来替代TCP,但结果证明这也非常困难。无奈之下,我 们只能尝试同时改进TCP协议本身和基于TCP的上层协议。
    简单来说,我们可以通过更好的利用TCP来减少传输过程中的中断,并充分挖掘利用那些本 可以用于发送/接受更多数据的时间。下面几段我们将会着重讨论这些问题。
    2.4 传输大小和资源数量
    如果仔细观察那些最流行的网站首页所需要下载的资源,会发现一个非常明显的趋势。近年 来加载网站首页接受的数据量在逐渐增加,并已经超过了1.9MB。但更重要的是:平均每个页面为了完成渲染需要加载超过100个独立资源。
    正如下图所示,这种趋势已经持续了很长一段时间,并且没有减缓的迹象。该图表中绿色直 线展示了传输数据大小的增长,红色直线展示了平均请求资源数量的增长。

  1. {failImgCache = [];}if(failImgCache.indexOf(src) == -1 && src.trim().length){failImgCache.push(src);}$(this).closest('.md-image').addClass('md-img-error').removeClass('md-img-loaded');" onload="var src = window.removeLastModifyQuery(this.getAttribute('src'));if(!src.trim()) return;if(loadedImgCache.indexOf(src) == -1 && src.trim().length){loadedImgCache.push(src);}$(this).closest('.md-image').addClass('md-img-loaded').removeClass('md-img-error');" style="box-sizing: border-box; border-width: 0px 4px 0px 2px; border-right-style: solid; border-left-style: solid; border-right-color: transparent; border-left-color: transparent; vertical-align: middle; max-width: 100%; cursor: default;">
    2.5 恼人的延迟
    HTTP 1.1对网络延迟非常敏感。部分原因是HTTP Pipelining还存有很多问题,所以对大部分用户来说这项技术是被默认关闭的。
  2. {failImgCache = [];}if(failImgCache.indexOf(src) == -1 && src.trim().length){failImgCache.push(src);}$(this).closest('.md-image').addClass('md-img-error').removeClass('md-img-loaded');" onload="var src = window.removeLastModifyQuery(this.getAttribute('src'));if(!src.trim()) return;if(loadedImgCache.indexOf(src) == -1 && src.trim().length){loadedImgCache.push(src);}$(this).closest('.md-image').addClass('md-img-loaded').removeClass('md-img-error');" style="box-sizing: border-box; border-width: 0px 4px 0px 2px; border-right-style: solid; border-left-style: solid; border-right-color: transparent; border-left-color: transparent; vertical-align: middle; max-width: 100%; cursor: default;">
    HTTP 1.1对网络延迟非常敏感。部分原因是HTTP Pipelining还存有很多问题,所以对大部分用户来说这项技术是被默认关闭的。
    虽然近几年来网络带宽增长非常快,然而我们却并没有看到网络延迟有对应程度的降低。在 高延迟的网络环境中(比如移动设备),即使拥有高连接速率,也很难获得优质快速的网络 体验。
    另外一个需要低延迟的场景是某些视频服务,如视频会议、游戏和其它类似无法预先发送资 源请求的情况。
    2.6 线头阻塞(Head of line blocking)
    HTTP Pipelining是这样一种技术:在等待上一个请求响应的同时,发送下一个请求。(译者 注:作者这个解释并不完全正确,HTTP Pipelining其实是把多个HTTP请求放到一个TCP连接 中一一发送,而在发送过程中不需要等待服务器对前一个请求的响应;只不过,客户端还是 要按照发送请求的顺序来接收响应。)但就像在超市收银台或者银行柜台排队时一样,你并不 知道前面的顾客是干脆利索的还是会跟收银员/柜员磨蹭到世界末日(译者注:不管怎么说, 服务器(即收银员/柜员)是要按照顺序处理请求的,如果前一个请求非常耗时(顾客磨 蹭),那么后续请求都会受到影响),这就是所谓的**线头阻塞(Head of line blocking)
    **
    当然,你可以在选择队伍时就做足准备,去排一个你认为最快的队伍,或者甚至另起一个新 的队伍(译者注:即新建一个TCP连接)。但不管怎么样,你总归得先选择一个队伍,而且 一旦选定之后,就不能更换队伍。
    但是,另起新队伍会导致资源耗费和性能损失(译者注:新建 TCP 连接的开销非常大)。这种另起新队伍的方式只在新队伍数量很少的情况下有作用,因此它并不具备可扩展性。(译者注:这段话意思是说,靠大量新建连接是不能有效解决延迟问题的,即HTTP Pipelining并不能彻底解决Head of line blocking问题。)所以针对此问题并没有完美的解决方案。
    这就是为什么,即使在2015年的今天,大部分桌面浏览器仍然会选择默认关闭HTTP pipelining这一功能的原因。
    3 那些年,克服延迟之道
    再困难的问题也有解决的方案,但这些方案却良莠不齐。
    3.1 Spriting
    Spriting是一种将很多较小的图片合并成一张大图,再用JavaScript或者CSS将小图重新“切 割”出来的技术。
    网站可以利用这一技巧来达到提速的目的——在HTTP 1.1里,下载一张大图比下载100张小图 快得多。
    但是当某些页面只需要显示其中几张小图时,这种方案的缺点就凸显出来了:它必须将整张 大图都从cache里取出,而不能将最频繁使用的那些图片保留在cache里。
    3.2 内联(Inlining)
    Inlining是另外一种防止发送很多小图请求的技巧,它将图片的原始数据嵌入在CSS文件里面 的URL里。而这种方案的优缺点跟Spriting很类似。
    .icon1 {
    background: url(data:image/png;base64,<data>) no-repeat;
    }
    .icon2 {
    background: url(data:image/png;base64,<data>) no-repeat;
    }
    10 那些年,克服延迟之道
    3.3 拼接(Concatenation)
    大型网站往往会包含大量的JavaScript文件。一些前端工具可以帮助开发人员将这些文件合并 为一个大的文件,从而让浏览器能只花费一个请求就将其下载完,而不是发无数请求去分别 下载那些琐碎的JavaScript文件。但凡事往往有利有弊,如果某页面只需要其中一小部分代 码,它也必须下载完整的那份;而文件中一个小小的改动也会造成大量数据的被重新下载。
    这种方案也给开发者造成了很大的不便。
    3.4 分片(Sharding)
    最后一个我要说的性能优化技术叫做Sharding。顾名思义,Sharding就是把你的服务分散在 尽可能多的主机上。这种方案乍一听比较奇怪,但是实际上在这背后却蕴藏了它独辟蹊径的 道理!
    最初的HTTP 1.1规范提到一个客户端最多只能对同一主机建立两个TCP连接。因此,为了不 和规范冲突,一些聪明的网站使用了新的主机名,这样的话,用户就能和网站建立更多的连 接,从而降低载入时间。
    后来,两个连接的限制被取消了,现在的客户端可以轻松地和每个主机建立6-8个连接。但由 于连接的上限依然存在,所以网站还是会用这种技术来提升连接的数量。而随着资源个数的 提升(上面章节的图例),网站会需要更多的连接来保证HTTP协议的效率,从而提升载入速 度。在现今的网站上,使用50甚至100个连接来打开一个页面已经并不罕见。根 据httparchive.org的最新记录显示,在Top 30万个URL中平均使用40(!)个TCP连接来显示 页面,而且这个数字仍然在缓慢的增长中。
    另外一个将图片或者其他资源分发到不同主机的理由是可以不使用cookies,毕竟现今cookies 的大小已经非常可观了。无cookies的图片服务器往往意味着更小的HTTP请求以及更好的性 能!
    下面的图片展示了访问一个瑞典著名网站的时产生的数据包,请注意这些请求是如何被分发 到不同主机的。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,158评论 4 370
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,600评论 1 307
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 111,785评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,655评论 0 220
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,075评论 3 295
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,002评论 1 225
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,146评论 2 318
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,918评论 0 211
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,671评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,838评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,318评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,636评论 3 263
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,343评论 3 244
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,187评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,982评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,126评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,934评论 2 279

推荐阅读更多精彩内容

  • jHipster - 微服务搭建 CC_简书[https://www.jianshu.com/u/be0d56c4...
    quanjj阅读 772评论 0 2
  • 这是本人撸完vue文档,看了github上一些 vue demo 后直接撸的项目,难度适中,适合各种小白入门。用到...
    Chance722阅读 2,047评论 12 41
  • 【一】对儿童健康有益的营养素及主要来源 蛋白质:日常中应该有50%的蛋白质来源于动物性食物,如鱼肉、鸡蛋、牛奶和禽...
    金秒学堂阅读 832评论 0 0
  • 2017/07/27 (140-139) 周四 晴 #to do list# 1、TEM8✅ 2、背诵7-8✅ 3...
    征人随说阅读 122评论 0 0
  • 基础类型 虽然Swift是一个为开发iOS和OS X app设计的全新编程语言,但是Swift的很多特性还是跟C和...
    xxxiharmi阅读 291评论 0 0