HTTP协议学习(一)

HTTP协议学习(一)

背景

up二刷《Http/2 in Action》时,记录一些自认为重要的知识点;

内容

HTTP1.1根本的问题

  1. 一个域名下的多个请求需要排队执行,不能并发的获取资源。这样就造成了时间的浪费。这种现象会随着资源数量的增多更加严重。也可以说是客户端和服务端处理资源的时间远小于http消息传输时间;

HTTP/1.1管道化技术可以解决该问题,但由于多种原因,它很难实现,易于出错,并且没有获得Web浏览器和Web服务器的良好支持。因此,它很少被使用。没有一个主流的Web浏览器支持管道化技术。管道化也存在队头阻塞问题,即使后发送的请求资源已经准备完成,但是它还是要等待在它之前发送请求的资源等待完成。

  1. 协议会因为等待响应会阻塞发送。即使客户端请求一发送完成,但是由于它没有返回,也不会发送请求二。 在最开始的环境http只用来传输一些静态的小的html页面,不会出现这种问题;但是由于现在网页需要的资源越来越多,这个缺点会保留的更严重。
  2. 文本协议,对开发人员友好,但是对机器并不友好。文本协议导致消息较大,不能高效编码数据。
  3. HTTP首部重复问题;比如cookie信息不是每个请求都需要,但是每个请求都自动携带了。另外头部信息随着越来越复杂的请求导致其迅速膨胀。可能造成头重脚轻的情况产生。
  4. 纯文本协议存在安全和隐私问题(https解决),无状态问题(cookie解决)。

HTTP1.1现有优化方案

  • 使用多个HTTP链接。
  • 合并HTTP请求。
  • 优先请求关键css
  • 减小下载资源的大小(压缩)
  • 减少浏览器的渲染任务(更高效的CSS和JavaScript)

使用多个HTTP链接

打开多个连接是解决HTTP/1.1阻塞问题的最简单方法,这样可以同时开启多个HTTP请求。另外,与管道化技术不同,该技术不会导致HOL阻塞,因为每个HTTP连接都独立于其他HTTP连接。因此,大多数浏览器可以为每个域名打开6个连接

为了进一步突破6个连接的限制,网站可能把资源分别放在不同的域名下。这种技术叫做域名分片。

这种方式也有缺点,因为开启多个HTTP链接对于客户端和服务端都有额外的开销,最主要的是TCP链接时间,维护链接需要更多的内存和CPU资源。

TCP链接的创建和维护是很消耗资源的操作,多个链接就会导致浪费。另外由于TCP特有的流量控制机制,慢启动的特性也会导致新连接在开始时的流量很低。

TCP建立之后,创建加密的HTTPS协议也需要开销。

另外,当这些新增的TCP链接达到了TCP的最佳效率,网页资源基本加载完成了,也就说最佳状态却没有得到应用。

综上所述,开启多个TCP链接并不是解决HTTP/1问题的最佳答案。

发送更少的请求

  • 通过http首部配置实现;
  • 打包合并静态资源(精灵图)

SPDY

spdy是一种二进制协议,它的特性包括: 流多路复用,请求优先级和HTTP首部压缩。

将文本协议转换成二进制协议这个改动使得我们可以在一个连接上处理较小的消息,然后将它们合并为较大的HTTP消息,这跟TCP将HTTP消息拆分为TCP数据包的模式非常像,而且这种拆分对于大多数HTTP实现来说是透明的。SPDY在HTTP层实现了TCP的相关概念,所以它可以同时传输不同的HTTP消息。

HTTP/2

http2其实是SPDY协议的标准化版本。

新增的概念

  • 二进制协议
  • 多路复用
  • 流量控制功能
  • 数据流优先级
  • 首部压缩
  • 服务端推送

HTTP2的变化主要是在网络中的传输方式有关。在http语义层和http1基本保持一致。

HTTP2和HTTPS有很多相似点,它们都是在发送前将标准HTTP消息用特殊格式封装,服务器在收到之后在解开。

二进制协议的优点

​ HTTP/1和HTTP/2的主要区别之一是,HTTP/2是一个二进制的、基于数据包的协议,而HTTP/1是完全基于文本的。

纯文本协议要求先发完请求,并接收完响应之后,才能开始下一个请求。

HTTP/1.0引入二进制的HTTP消息体,支持在响应中发送图片或其他媒体文件。HTTP/1.1引入管道化和分块编码。分块编码可以理解为服务器将大的资源切分成几块小的发送。这样小的往返时间就快很多。便于别的请求发送。等大资源其它块可用了在返回。不管是管道化还是分块编码都存在HOL问题。

HTTP/2变成了一个完全的二进制协议,HTTP消息被分成清晰定义的数据帧发送。

这里的帧和支撑HTTP连接的TCP数据包类似。当收到所有的数据帧后,可以将它们组合为完整的HTTP消息。尽管和TCP有很多相同点,但HTTP/2通常还是建立在TCP之上的,它没有替换TCP(但是Google正在尝试用QUIC替换TCP,并且在其上使用更轻的HTTP/2实现)。底层协议,如TCP,可以保证消息有序到达,所以不需要在HTTP/2中添加此类逻辑。

多路复用代替同步请求

HTTP/1是一种同步、独占得请求-响应协议。

HTTP/2允许在单个连接上同时执行多个请求,每个HTTP请求或响应使用不同的流。通过使用二进制分帧层,给每个帧分配一个流标识符,以支持同时发出多个独立请求。当接收到该流的所有帧时,接收方可以将帧组合成完整消息。

HTTP/2连接在请求发出后不需要阻塞到响应返回(如第2章中所述,HTTP/1.1会阻塞)。

每个请求都有一个新的、自增的流ID。返回响应时使用相同的流ID,也就是说和HTTP连接一样,流是往返的。响应完成后,流将被关闭。在这一点上HTTP/2流和HTTP/1.1连接又有所不同。因为HTTP/2中流会被丢弃而且不能重用,而HTTP/1.1保持连接打开,并且可以重新用它来发送另一个请求。

为了防止流id重复,定义客户端的流id是奇数,服务端的流id是偶数。ID为0的流(图中未显示出)是客户端和服务器用于管理连接的控制流。

HTTP/2使用多个二进制帧发送HTTP请求和响应,使用单个TCP连接,以流的方式多路复用。

HTTP/2与HTTP/1的不同主要在消息发送的层面上,在更上层,HTTP的核心概念不变。例如,请求包含一个方法(例如GET)、想要获取的资源(例如/styles.css)、首部、正文、状态码(例如200、404)、缓存、Cookie等,这些都与HTTP/1保持一致。

流的优先级和流量控制

HTTP/1是单独的请求-响应协议,所以优先级可以根据请求顺序来决定。

HTTP/2中大多数可以同时申请100个流的请求,虽然解决了1中同时请求的问题,但是如果不存在优先级机制100个流中的较低优先级资源(图像)会占用带宽,导致整个页面加载缓慢。

流的优先级控制是通过这种方式实现的:当数据帧在排队时,服务器会给高优先级的请求发送更多的帧。也就说客户端发送之后,服务器端这边会存在一个队列来接收和缓存帧,在这个队列中会根据流id来排序,从而优先处理优先级高的流的帧

首部压缩

HTTP首部(包括请求首部和响应首部)用于发送与请求和响应相关的额外信息。

HTTP首部信息有很多信息都是重复的,多个资源的请求使用的首部也往往相同。

• Cookie——Cookie随着每个发向服务器的请求被发送(除非像Amazon一样使用未经授权的请求,见第2章,但这是特殊情况,并不常见)。Cookie首部有可能会变得非常大,而且通常只有HTML文档需要用到它,但是每个请求都会带上Cookie。
• User-Agent——此首部常用来指示用户在使用的浏览器。在同一个会话中,浏览器从来不会发生变化,但它还是会随着每个请求被发送。
• Host——此首部用来修饰请求URL。发向同一个主机的Host首部内容通常相同。
• Accept——此首部定义了客户端期望的响应格式(浏览器接受的可处理的图片格式等)。如果不升级浏览器,那么浏览器所支持的内容格式不会变化,每个请求的内容类型(图片、文档、字体等)对应的Accept首部值不同,但是针对每个类型的不同请求,它们的值是一样的。
• Accept-Encoding——此首部定义了压缩格式(通常是gzip、deflate,以后会经常遇到br,因为浏览器开始支持更新的brotli压缩)。和Accept首部相同,在同一个会话期间,这个首部的值也不会发生变化。

重复的情况就会导致浪费资源。在HTTP/1中允许压缩HTTP正文内容(通过Accept-Encoding首部),但是不会压缩HTTP首部。

HTTP/2中引入了首部压缩的概念,但是它和正文压缩不通,它支持了跨请求压缩,避免正文压缩所使用算法的安全问题。4.1

HTTP的正文压缩通常用于文本数据,媒体数据一般都通过指定的格式提前压缩过了。当发送请求的时候客户端通过accept-encoding 来告诉服务器它所支持的压缩算法。
客户端和服务器正文的压缩算法都是基于deflate压缩算法的,但是它被证实不安全了。我们可以根据使用数据长度来猜测内容,特别是当你能影响内容中的一部分时。这种方法不适用与首部压缩,因为你可以通过重试法来猜测重要header的值(比如token)。你只需要把token的值用不同的值来请求,你最终会发现至少有一个测试(token=s)比其他测试要短,是因我deflate把s替换成比它更短的值了。那么你就可以确认token的第一个字母是s。重复这个过程你就可以得到整个token。

HTTP2使用HPACK算法来压缩首部,解决了安全问题。HPACK算法基于查询表(包括动态表和静态表)和Huffman编码来实现。

服务端推送

HTTP/2中另外一个重要的不同,添加了服务端推送的概念。它允许服务端针对一个请求发送多个响应。也就变成了请求-多响应的模式。

比如:当主页加载完成后 ,渲染之前,页面需要css或者js。传统http/1就需要继续发请求来获取,而HTTP/2在页面请求之后,由服务器自动把这些资源推送过来,等页面加载完成直接可以使用了,加快了页面的渲染时间。

但是也不是只有好处,如果使用不当也很容易浪费带宽。

总结

这篇博文介绍了http1存在的一些问题,已经当前现有的解决方案,从而引出http2,并简单介绍了http2的新特性。


版权声明:本文为qq_36628536原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。