闲聊HTTP/2.0

2023-05-06 19:31:59 浏览数 (1)

HTTP 从上世纪 90 年代初就出现了,在 2010 年到 2015 年之间,单个网页传输的数据量增长到了三倍,获取所有数据所需的请求数量也稳步上升。HTTP 使用的目的及场合与当初设计的目的及场合完全不一样,当时合理的设计理念现在对开发和性能来说都成为了负担。目前的一些最佳做法,例如将所有 JavaScript 整合到一个文件中,仅仅是为了解决 HTTP/1 的不足之处,这时候 HTTP/2 应运而生。HTTP/2它不仅可以向下兼容,而且解决了 HTTP/1 存在的一些问题。

HTTP/1 问题之一,队头阻塞。

HTTP/1 无法很好地处理大量请求,我们有太多请求的原因之一是队头阻塞,幸运的是出现了 HTTP/2。

队头阻塞是指某个请求阻止系统完成其他请求,更详细的说是一列的第一个数据包(队头)受阻而导致整列数据包受阻。

浏览器最多会向同一服务器开启六个连接,意味着最多同时有六个请求,至少要等待请求被发送然后返回响应,这两个称为往返过程。对于好的连接,往返时间可以在20 到 50 毫秒之间,我们来快速演示一个数学流程: 假设一个网站需要发送 100 个请求才能完全加载,我们可以并行处理六个请求,意味着理想情况下,每个连接需要发出 17 个请求才能下载所有 100 个请求,每个请求的平均往返时间大概是 35 毫秒,结果为 525 毫秒,大约半秒的等待时间什么都不能做,前提是实际传输请求的文件不需要任何时间。如果传输的文件很大,那么这个数字将变得很大。这个往返时间是平均值,如果网络连接不稳定或很慢,情况会更糟糕。队头阻塞对网站性能来说影响极大。

HTTP/1 问题之二,未压缩标头。

为了缩短数据发送时间,很多网站都使用 gzip 或其他适用于网络的压缩算法压缩资源,HTML 模板项目使用 gzip 压缩算法。数据压缩作用很大,但是请求和响应报头依然没有压缩,仔细思考下会发现这不合理,它们是纯文本,完全可以压缩,此外,它们在很多请求中都是重复的,Host 报头 Cookie和其他一些报头始终不变。Google 的研究报告指出,报头平均占用 800 字节,我们来看看可能会节省的空间,如果一个网站发出 100 个请求,报头大约占用 80 字节的数据,很多数据都是多余的,如果能够压缩报头,将节省很多空间,对于 HTTP1 来说无法压缩,但是对于 HTTP2 我们可以压缩。

HTTP/1 问题之三,安全性。

HTTP/2 处理的另一个完全不同的领域是安全性。电子商务越来越热门,处理信用卡和合同的敏感数据也变得热门起来。如果网站不用 TLS 来处理此类数据,那么绝对是很大的疏忽,因此 TLS 成为了HTTP/2 规范的必要部分。HTTP/2 存在非压缩版本,但是所有的大型网站都不支持这种版本了。我们之前讨论过 TLS,在 HTTP/2 中使用 TLS 的过程完全没变。

HTTP/2 如何解决这些问题呢?普通人能够读懂请求和响应报头,所以肯定要处理这种问题,这是改善 HTTP/2 性能的第一步。有这些报头很方便,但是纯文本形式的 HTTP/1 报头对任何人都没好处,以文本的形式呈现浪费了宝贵的空间,其实一个位就能搞定。但是别担心,Wireshark 或 DevTools 等工具依然使你能够查看报头,即使 HTTP/2 也如此。

HTTP / 2初始草案(它是SPDY的副本)的其他性能改进来自请求和响应的多路复用,以避免HTTP 1中的某些队头阻塞问题(即使使用HTTP流水线),标头压缩请求的优先级。请注意,由于HTTP / 2使用单个TCP连接,因此可能仍存在一些残留的队头阻塞。 HTTP / 2不再支持HTTP 1.1的分块传输编码机制,因为它为数据流提供了自己的,更有效的机制。

HTTP/2 解决第一个问题是队头阻塞,它通过一种叫做多路复用的技巧来解决这一问题,多路复用是个比较华丽的词,表示将多个信号整合成一个新的信号,对于 HTTP/2,我们现在用一个连接而不是六个连接,咋听起来像是一种可怕的退步,但是我们使用单个连接的方式与 HTTP/1 不同,在 HTTP/1 中称为专属连接的连接,现在是信息流。所有信息流共享一个连接,这些信息流拆分为帧,并在该单个连接上多路复用。当一个信息流被阻塞时,另一个信息流可以获取该连接,并充分利用本来会成为闲置时间的时段,队头阻塞问题解决了。

解决第二个问题是HTTP/2 可以压缩报头数据,对于 HTTP/2报头不仅通过 gzip 被压缩,并且工程师设计出专门针对报头的特殊结构和 HTTP/2 多路复用功能的压缩算法,所有信息流不仅共享连接并且共享压缩器,意味着报头不用被发送两次,因为压缩器能够识别报头之前被发送过,所以会改为发送引用。这样HTTP/2传输字节比HTTP/1少,网站加载速度也会更快。

例如下图, Cookie 是非常长的报头,因此如果在这里插入和前面第三个请求一样的 Cookie,而不是插入实际值,这会有很大的优势。

该压缩算法的细节内容和工作原理见这里:HPACK:HTTP / 2的标头压缩

HTTP/2 带来了很多变化,但是如何从 HTTP/1,转换为强大的 HTTP/2 呢?如何以最佳方式满足所有用户的需求?

随着 HTTP/2 中的队头阻塞消失了,因此没有必要合并 JavaScript 或 CSS 了。

如果合并实际上让情况变得更糟糕,假设要更新一个缓存的文件,如果你修正了 JavaScript 文件中的一个拼写错误,例如缺少一个花括号,则用户必须重新下载整个 JavaScript,而不是仅仅发生更改的片段。如果每个 JavaScript 文件都是分开的,则只会让单个文件的缓存变得无效而已。

但压缩报头在发送更多请求时变得更高效,发送的请求越多,重复使用的标头越多(后续直接发送引用即可),缩小和压缩 JavaScript CSS 及图片依然是很好的做法,哪怕是一个字节都值得节省,尤其是在发展中国家/地区,节省字节就是节省费用,此外关于渲染性能的所有建议依然有效,例如推迟 JavaScript 或内嵌样式,花时间构建完善的客服支持服务也不例外。最重要的是 HTTP/2 可以向下兼容,所有支持 HTTP/2 的服务器都将支持 HTTP/1,不支持 HTTP/2 的客户端将直接后退成支持HTTP/1,并且和之前一样运转而这些客户端越来越少,因此不用担心使用 HTTP/2 有何问题,因此你完全可以针对 HTTP/2 优化网站而不用太关心 HTTP/1。

对于 HTTP/2 ,任何关于合并文件或将子画面合并为图片的步骤都需要重新考虑,大部分情况下这么做都不合适,因为让缓存变得很低效。压缩依然是很好的做法,因为它降低了需要传输的字节数,因此压缩 JavaScript CSS 和标记是正确的。而共享资源不合适,因为使得 HTTP/2 报头压缩器效率更低,并导致浏览器打开新的连接,这样就会代价很高。使用单个 CDN 就可以胜过共享的不足之处,因为它使得资源在地理上更接近用户,并缩短了往返时间。

0 人点赞