- 之前对 TCP 连接及其性能含义进行了精要的介绍,现在切回到 HTTP 上来。
1. Connection 首部
- HTTP 允许在客户端和最终的源端服务器之间存在一串 HTTP 中间实体(代理、高速缓存等)。可以从客户端开始,逐跳将 HTTP 报文经过这些中间设备,转发到源端服务器上去(或者进行反向传输)。
- Connection:
- 类型:通用首部
- 注释:虽然 RFC 2616 没有专门声明将 keep-alive 作为连接标记使用,有些 (包括那些将HTTP/1.1 作为版本号发送的)浏览器还是会在发起请求时使用它。
- 基本语法:Connection: 1# (connection-token)
- 举例:Connection: close
- Connection 首部是个多少有点儿过载了的首部,它可能会把你搞晕。这个首部用于扩展了 keep-alive 连接的 HTTP/1.0 客户端,keep-alive 连接用于控制信息。在HTTP/1.1 中,能识别出大部分较老的语义,但这个首部被赋予了新的功能。
- 在 HTTP/1.1 中,Connection 首部的值是一个标记列表,这些标记对应各种首部名称。应用程序收到带有 Connection 首部的 HTTP/1.1 报文后,应该对列表进行解析,并删除报文中所有在 Connection 首部列表中出现过的首部。它主要用于有代理网络环境,这样服务器或其他代理就可以指定不应传递的逐跳首部了。
- close 是一个典型的标记值。这个标记意味着响应结束之后,连接会被关闭。不支持持久连接的 HTTP/1.1 应用程序要在所有请求和响应中插入带有 close 标记的 Connection 首部。
- Connection 首部可以承载 3 种不同类型的标签,因此有时会很令人费解:
- HTTP 首部字段名,列出了只与此连接有关的首部;
- 任意标签值,用于描述此连接的非标准选项;
- 值 close,说明操作完成之后需关闭这条持久连接。
- 如果 Connection 中包含了一个 HTTP 首部字段的名称,那么这个首部字段就包含了与一些连接有关的信息,不能将其转发出去。在将报文转发出去之前,必须删除 Connection 首部列出的所有首部字段。由于 Connection 首部可以防止无意中对本地首部的转发,因此将逐跳首部名放入 Connection 首部被称为“对首部的保护”。
- HTTP 应用程序收到一条带有 Connection 首部的报文时,接收端会解析发送端请求的所有选项,并将其应用。然后会在将此报文转发给下一跳地址之前,删除 Connection 首部以及 Connection 中列出的所有首部。而且,可能还会有少量没有作为 Connection 首部值列出,但一定不能被代理转发的逐跳首部。其中包括 Prxoy-Authenticate、Proxy-Connection、Transfer-Encoding 和 Upgrade。
2. 串行事务处理时延
- 串行加载缺点一:如果只对连接进行简单的管理,TCP 的性能时延可能会叠加起来。
- 举例:假设有一个包含了 3 个嵌入图片的 Web 页面。浏览器需要发起 4 个 HTTP 事务来显示此页面: 1 个用于顶层的 HTML 页面,3 个用于嵌入的图片。如果每个事务都需要(串行地建立)一条新的连接,那么连接时延和慢启动时延就会叠加起来。
- 串行加缺点二:有些浏览器在对象加载完毕之前无法获知对象的尺寸,而且它们可能需要尺寸信息来决定将对象放在屏幕的什么位置上,所以在加载了足够多的对象之前,无法在屏幕上显示任何内容。在这种情况下,可能浏览器串行装载对象的进度很正常,但用户面对的却是一个空白的屏幕,对装载的进度一无所知。(注:HTML 的设计者可以在图片等嵌入式对象的 HTML 标签中显式地添加宽高属性,以消除这种“布局时延”。显式地提供了嵌入图片的宽度和高度,浏览器就可以在从服务器收到对象之前确定图形的布局了。)
- 后面几节将讨论 4 种提高 HTTP 连接性能的方法:
- 并行连接:通过多条 TCP 连接发起并发的 HTTP 请求。
- 持久连接:重用 TCP 连接,以消除连接及关闭时延。
- 管道化连接:通过共享的 TCP 连接发起并发的 HTTP 请求。
- 复用的连接:交替传送请求和响应报文(HTTP/2.0中实现)。