HTTP1.1协议现状、问题和解决方案
HTTP的现状
最早的HTTP协议非常简单,只能用来传送文本,方法也只有GET,后来逐步发展到1.1,能够支持多种MIME格式数据(如文本、文件),支持GET,POST,HEAD,OPTIONS,PUT,DELETE,TRACE和CONNECT方法,这些新的方法(HTTP METHODS)也是后来RESTful服务接口风格的技术基础。目前几乎所有互联网上的内容都采用了HTTP1.1作为通信协议。但随着互联网的发展,也逐渐暴露出一些问题:
过于庞大
HTTP刚诞生的时候只被当作是一个相对简单直观的协议,但时间证明了早期的设计并不尽人意。于1996年发布的描述HTTP1.0规范的RFC1945只有60页,但仅仅3年之后描述HTTP1.1规范的RFC2616就一下增长到了176页。而当IETF小组对该规范进行更新时,它更是被拆分成了总页数更多的六个文档(这就是RFC7230及其文件族的由来与诞生)。总而言之,HTTP1.1包含了太多细节和可选的部分,这让它变得过于庞大。
过多的可选项
HTTP1.1不仅包含了非常多的细枝末节,同时也为未来的扩展预留了很多选项。这种事无巨细的风格导致在现有的软件生态中,几乎没有任何实现真正实现了协议中提及的所有细节,甚至要弄清楚“所有细节”到底包括哪些细节都非常困难。而这也导致了很多最初不常用的功能在后来的实现中很少会被支持,而有些最初实现了的功能,却又很少被使用。
随着时间推移,这些当初看似被边缘化的功能逐渐被用上,客户端和服务器的互操作性(interoperability)问题就被暴露了出来。HTTP管道(HTTP Pipelining)就是一个例子。
未能被充分利用的TCP
HTTP1.1很难榨干TCP协议所能提供的所有性能。HTTP客户端和浏览器必须要找到新的解决方案来降低页面载入时间。
与此同时,人们也尝试去用新的协议来替代TCP,但结果证明这也非常困难。无奈之下,我们只能尝试同时改进TCP协议本身和基于TCP的上层协议。
简单来说,我们可以通过更好的利用TCP来减少传输过程中的暂停,并充分挖掘利用那些本可以用于发送/接受更多数据的时间。下面几段我们将会着重讨论这些问题。
传输大小和资源数量
如果仔细观察打开那些最流行的网站首页所需要下载的资源的话,会发现一个非常明显的趋势。近年来加载网站首页需要下载的数据量在逐渐增加,常常达到2M以上(主要是图片、样式和脚本)。但在这里我们更应该关心的是:平均每个页面为了完成显示与渲染所需要下载的资源数已经超过了100个。
恼人的延迟
HTTP1.1对网络延迟非常敏感。部分原因是HTTP Pipelining还存有很多问题,所以对大部分用户来说这项技术是被默认关闭的。
虽然近几年来网络带宽增长非常快,然而我们却并没有看到网络延迟有对应程度的降低。在高延迟的网络上(比如移动设备),即使拥有高连接速率,也很难获得优质快速的网络体验。
另外一个需要低延迟的场景是某些视频服务,如视频会议、游戏和一些类似无法预生成待发送数据流的服务。
线头阻塞(Headof line blocking)
HTTP Pipelining是这样一种技术:把多个HTTP请求放到一个TCP连接中一一发送,也就是说在服务器处理前面的请求时,客户端依然可以发送请求而无需等待,但是客户端还是要按照发送请求的顺序来接收响应。就像在超市收银台或者银行柜台排队时一样,你并不知道前面的顾客是干脆利索的还是会跟收银员纠缠很久,这就是所谓的线头阻塞(Head of line blocking)。
当然,你可以在选择队伍时候就做好功课,去排一个你认为最快的队伍,或者甚至另起一个新的队伍。但不管怎么样,你总归得先选择一个队伍,而且一旦选定之后,就不能更换队伍。
但是,另起新队伍会导致资源耗费和性能损失。这种另起新队伍的方式只在新队伍 数量很少的情况下有作用,因此它并不具备可扩展性。
这就是为什么,即使在2015年的今天,大部分桌面浏览器仍然会选择默认关闭HTTP pipelining这一功能的原因。
克服延迟之道
再困难的问题也有解决的方案,但这些方案却良莠不齐。
精灵图(Spriting)
Spriting是一种将很多较小的图片合并成一张大图,再用JavaScript或者CSS将小图重新“切割”出来的技术。
网站可以利用这一技巧来达到提速的目的——在HTTP1.1里,下载一张大图比下载100张小图快得多。
但是当某些页面只需要显示其中几张小图时,这种方案的缺点就凸显出来了:它必须将整张大图都从cache里取出,而不能 将最频繁使用的那些图片保留在cache里。
内联(Inlining)
Inlining是另外一种防止发送很多小图请求的技巧,它将图片的原始数据嵌入在CSS文件里面的URL里(主要使用base64编码)。而这种方案的优缺点 跟Spriting很类似。
.icon1{background:url(data:image/png;base64,<data>)no-repeat;} .icon2{background:url(data:image/png;base64,<data>)no-repeat;}
拼接(Concatenation)
大型网站往往会包含大量的JavaScript文件。一些前端工具可以帮助开发人员将这些文件合并为一个大的文件,从而让浏览 器能只花费一个请求就将其下载完,而不是发无数请求去分别下载那些琐碎的JavaScript文件。但凡事往往有利有弊,如果某页面只需要其中一小部分代码,它也必须下载完整的那份;而文件中一个小小的改动也会造成大量数据的被重新下载。
这种方案也给开发者造成了很大的不便。
分片(Sharding)
最后一个我要说的性能优化技术叫做Sharding。顾名思义,Sharding就是把你的服务分散在尽可能多的主机上。这种方案乍一听比较奇怪,但是实际上在这背后却蕴藏了它独辟蹊径的道理!
最初的HTTP1.1规范提到一个客户端最多只能对同一主机建立两个TCP连接。因此,为了不和规范冲突,一些聪明的网站使用了新的主机名,这样的话,用户就能和网站建立更多的连接,从而降低载入时间。
后来,两个连接的限制被取消了,现在的客户端可以轻松地和每个主机建立6-8个连接。但由于连接的上限依然存在,所以网站还是会用这种技术来提升连接的数量。而随着资源个数的提升,网站会需要更多的连接来保证HTTP 协议的效率,从而提升载入速度。在现今的网站上,使用50甚至100个连接来打开一个页面已经并不罕见。根据httparchive.org的最新记录显示,在Top 30万个URL中平均使用40(!)个TCP连接来显示页面,而且这个数字仍然在缓慢的增长中。
另外一个将图片或者其他资源分发到不同主机的理由是可以不使用cookies,毕竟现今cookies的大小已经非常可观了。无cookies的图片服务器往往意味着更小的HTTP请求以及更好的性能!
下面的图片展示了访问一个著名网站的时产生的数据包,请注意这些请求是如何被分发到不同主机的。
文章主要内容来自:
https://www.gitbook.com/book/bagder/http2-explained/
最新评论
- 相关文章
3D感知和建模关键硬件技术:双目、3D结构光和TOF
无论VR、AR和3D打印,其核心技术包含3D成像和建模。而3D建模属于劳动密集型的工作,耗时耗力,凡这类工作都会是被新技术革命的地方,自动3D建模技术就是为了解决...
如何使用BabylonJS加载OBJ或STL模型
BabylonJS(也就是babylon.js,这是一个和three.js类似的WebGL开发框架),更多的用在游戏领域。
本文说明和演示如何使用babylon.js来加载一个标准3d模型文...A-Frame WebVR(网页虚拟现实)快速开发入门教程
WebVR和WebGL应用程序接口使得我们已经可以在浏览器上创建虚拟现实(VR)体验,但从工程化的角度而言,开发社区还需要更多方便强大的开发库来简化编程,Mozilla的
CSS3特性查询(Feature Query: @supports)功能简介
这是2017年不能不了解和学习的一个CSS新特性,非常实用,考虑到现实世界浏览器的复杂性,该特性本应该先于其他新特性出来。我们已经知道使用媒体查询(Media Que...
Web界面编程状态变化和JS开发框架(React/Angular/Ember)
UI编程中的一个关键课题就是界面组件化(可复用)以及组件状态管理。稍早一些的windows程序员可能接触过MFC,其界面编程中有一个DDX(DoDataExchange)的机制,...
使用HTML5 FileReader和Canvas压缩用户上传的图片
手机用户拍的照片通常会有2M以上,这对服务器带宽产生较大压力。因此在某些应用下(对图片要求不那么高)我们可以在客户端来压缩图片,然后再提交给服务器。总体...
使用SVG和CSS3创建圆形进度条动画
圆形进度条是一个经典的控制面板元素,常用于显示任务进度,比如用户档案的完整程度,或者升级状态。有很多方法来实现圆形进度条,比如用JS, CSS3, Canvas, SVG...
三维向量的简单运算和实用意义
在WebGL的实际应用中我们广泛使用向量的几何运算来计算角度、距离,判断点线、点面之间的关系,比如物体之间的碰撞检测。本文简要介绍三维计算机图形学中常用的...
粒子运动模拟 - Verlet积分算法简介
Verlet算法是经典力学(牛顿力学)中的一种最为普遍的积分方法,被广泛运用在分子运动模拟(Molecular Dynamics Simulation),行星运动以及织物变形模拟等领域...
Three.js入门教程4 - 创建粒子系统动画
嗨,又见面了。这么说我们已经开始学习Three.js了,如果你还没有看过之前三篇教程,建议你先读完。如果你已经读完前面的教程了,你可能会想做一些关于粒子的东西。让我们直面这个话题吧,每个人都爱粒子效果。不管你是否知道,你可以很轻易地创建它们。
WebGL入门教程6 - 光照效果和Phong光照模型
正是因为有了光,世界才能被我们看见,在3D的世界里,光照给物体带来真实的视觉感受。当光照射在某一表面上时,它可能被吸收、反射或投射。其中入射到表面上的一...
WebGL入门教程3 - Canvas、Context、API和绘制一个矩形
WebGL入门教程2 - GPU基本概念和工作流水线(渲染管道)
如何使用CSS3/SCSS实现逼真的车窗雨滴效果
在天气预报类的Web移动应用中,常常需要实现屏幕的雨滴效果,表示阴雨天气。感觉上比较神奇,其实想通了,这个效果的实现只需要一点物理知识和CSS3的简单变换。实现一个小雨滴首先雨滴是一个个小的椭圆形元素:.raindrop
更多...