知识卡片
即时压缩与持久连接的冲突及分块传输编码解法
内容
持久连接靠”重用同一个TCP连接传输多个资源”省去重复建连成本,但这要求 客户端有除”连接关闭”之外的手段判断单个资源何时传完——最初这个手段就是 Content-Length,请求头明确告知资源总长度,收够字节数就算完成。这与压缩 产生了冲突:现代Web服务器普遍采用”即时压缩”(On-The-Fly Compression), 边压缩边输出,输出Header时压缩后的确切大小根本还不知道,Content-Length 自然给不出来。HTTP/1.0时代持久连接和即时压缩只能二选一(默认都不开)。 HTTP/1.1引入”分块传输编码”(Chunked Transfer Encoding)解决了这个死结: 响应体不再一次性给出总长度,而是拆成一系列”分块”依次发送,每块前面标注 自己的十六进制长度,最后用一个长度为0的分块表示资源结束——判断资源是否 传完不再依赖预先知道总长度,而是靠”看到结束标记”。这个设计同样解决了 Ajax、PHP等动态内容响应长度无法预知的老问题。到HTTP/2时代,由于多路 复用和单域名单连接的设计,”要不要保持持久连接”这个问题本身已经不存在 了,但分块编码/数据压缩节约带宽的价值依然存在。
参考来源
- 位置:《凤凰架构:构建可靠的大型分布式系统》第4章"透明多级分流系统"
4.3.2节"传输压缩"(源文件:_epub-src对应OEBPS/Text/chapter42.xhtml)
- 结论依据:原文说明即时压缩无法给出Content-Length,与依赖Content-Length
判断传输结束的持久连接机制产生冲突,HTTP/1.1引入分块传输编码用"长度为0
的分块标记结束"替代"预先声明总长度"来解决这一冲突,直接支撑本卡片结论。
- 原始内容:由于启用即时压缩后就无法给出Content-Length了,如果是HTTP/1.0
的话,持久连接和即时压缩只能二选一……HTTP/1.1版本中修复了这个缺陷,
增加了另一种"分块传输编码"的资源结束判断机制,彻底解决了Content-Length
与持久连接的冲突问题。