HTTP(Hypertext Transfer Protocol,超文本传输协议)是在万维网上进行通信时所使用的协议方案。HTTP最著名的是用于Web浏览器和Web服务器之间的双工通信。
HTTP:Web的基础
URI(Uniform Resource Identifier)
服务器资源名被称为统一资源标识符,URI就像是因特网上的邮件地址一样,在世界范围内唯一标识并定位信息资源。
URI有两种类型:URL和URN。
URL,统一资源定位符是资源标志符最常见的形式。URL描述了一台特定服务器上某资源的特定位置。现在,几乎所有URI都是URL。
URN,统一资源名。URN是作为特定内容的唯一名称使用的,与目前的资源所在地无关。通过URN,还可以用同一个名字通过多种网络访问协议来访问资源。URN依然处于试验阶段,还未大范围使用。
HTTP请求报文和相应报文
HTTP请求和相应报文的格式很类似,HTTP报文包括以下三个部分:
- 起始行
HTTP/1.0 200 OK - 首部字段
Content-type: text/plain
Content-length: 19 - 主体
I’m a message!
TCP/IP
TCP(Transmission Control Protocol),传输控制协议。
TCP提供了
无差错的数据传输
按序传输(数据总是会按照发送的顺序到达)
未分段的数据流(可以在任意时刻以任意尺寸将数据发送出去)
HTTP协议版本
HTTP/0.9
HTTP 的 1991 原型版本称为 HTTP/0.9。这个协议有很多严重的设计缺陷,只应 该用于与老客户端的交互。HTTP/0.9 只支持 GET 方法,不支持多媒体内容的 MIME 类型、各种 HTTP 首部,或者版本号。HTTP/0.9 定义的初衷是为了获取 简单的 HTML 对象,它很快就被 HTTP/1.0 取代了。HTTP/1.0
1.0 是第一个得到广泛使用的 HTTP 版本。HTTP/1.0 添加了版本号、各种 HTTP 首部、一些额外的方法,以及对多媒体对象的处理。HTTP/1.0 使得包含生动图 片的 Web 页面和交互式表格成为可能,而这些页面和表格促使万维网为人们广 泛地接受。这个规范从未得到良好地说明。在这个 HTTP 协议的商业演进和学术 研究都在快速进行的时代,它集合了一系列的最佳实践。
HTTP/1.0+
在 20 世纪 90 年代中叶,很多流行的 Web 客户端和服务器都在飞快地向 HTTP 中添加各种特性,以满足快速扩张且在商业上十分成功的万维网的需要。其中很 多特性,包括持久的 keep-alive 连接、虚拟主机支持,以及代理连接支持都被加 入到 HTTP 之中,并成为非官方的事实标准。这种非正式的 HTTP 扩展版本通常 称为 HTTP/1.0+。HTTP/1.1
HTTP/1.1 重点关注的是校正 HTTP 设计中的结构性缺陷,明确语义,引入重要 的性能优化措施,并删除一些不好的特性。HTTP/1.1 还包含了对 20 世纪 90 年 代末正在发展中的更复杂的 Web 应用程序和部署方式的支持。HTTP/1.1 是当前 使用的 HTTP 版本。HTTP/2.0(HTTP-NG)
HTTP-NG 是 HTTP/1.1 后继结构的原型建议,它重点关注的是性能的大幅优化, 以及更强大的服务逻辑远程执行框架。HTTP-NG 的研究工作终止于 1998 年,编 写本书时,还没有任何要用此建议取代 HTTP/1.1 的推广计划。更多信息请参见 第 10 章。
Web的结构组件
代理
代理,位于客户端和服务器之间的HTTP中间实体。
代理位于客户端和服务器之间,接收所有客户端的HTTP请求,并将这些请求转发给服务器(可能会对请求进行修改之后转发)。
出于安全考虑,通常会将代理作为转发所有Web流量的可信任中间节点使用。代理还可以对请求和响应进行过滤。
缓存
缓存,HTTP的仓库,使常用页面的副本可以保存在离客户端更近的地方。
Web缓存或代理缓存是一种特殊的HTTP代理服务器。
网关(gateway)
网关,连接其他应用程序的特殊Web服务器。
网关是一种特殊的服务器,作为其他服务器的中间实体使用。通常用于将HTTP流量转换成其他协议。
隧道(tunnel)
隧道,对HTTP通信报文进行盲转发的特殊代理。
隧道是建立起来之后,就会在两条连接之间对原始数据进行盲转发的HTTP应用程序。HTTP隧道通常用来在一条或多条HTTP连接上转发非HTTP数据,转发时不会窥探数据。
HTTP 隧道的一种常见用途是通过 HTTP 连接承载加密的安全套接字层(SSL, Secure Sockets Layer)流量,这样 SSL 流量就可以穿过只允许 Web 流量通过的防 火墙了。如图 1-14 所示,HTTP/SSL 隧道收到一条 HTTP 请求,要求建立一条到目 的地址和端口的输出连接,然后在 HTTP 信道上通过隧道传输加密的 SSL 流量,这 样就可以将其盲转发到目的服务器上去了。
Agent代理
Agent代理,发起自动HTTP请求的半智能Web客户端。
所有发布Web请求的应用程序都是HTTP Agent代理,包括Web浏览器、搜索引擎机器人。
连接管理
HTTP事务的时延
与建立 TCP 连接,以及传输请求和响应报文的时间相比,事务处理时间可能 是很短的。除非客户端或服务器超载,或正在处理复杂的动态资源,否则 HTTP 时 延就是由 TCP 网络时延构成的。
性能聚焦区域
常见的TCP相关时延:
- TCP连接建立握手
- TCP慢启动拥塞控制
- 数据聚焦的Nagle算法
- 用于捎带确认的TCP延迟确认算法
- TIME_WAIT时延和端口耗尽
TCP慢启动
TCP数据传输的性能还取决于TCP连接的使用期。TCP连接会随着时间进行自我“调谐”,起初会限制连接的最大速度,如果数据成功传输,会随着时间的推移提高传输的速度。这种调谐被称为TCP慢启动,用于防止因特网的突然过载和拥塞。
TCP 慢启动限制了一个 TCP 端点在任意时刻可以传输的分组数。简单来说,每成功 接收一个分组,发送端就有了发送另外两个分组的权限。如果某个 HTTP 事务有大 量数据要发送,是不能一次将所有分组都发送出去的。必须发送一个分组,等待确 认;然后可以发送两个分组,每个分组都必须被确认,这样就可以发送四个分组了, 以此类推。这种方式被称为“打开拥塞窗口”。
由于存在这种拥塞控制特性,所以新连接的传输速度会比已经交换过一定量数据的、 “已调谐”连接慢一些。由于已调谐连接要更快一些,所以 HTTP 中有一些可以重用 现存连接的工具。本章稍后会介绍这些 HTTP“持久连接”。
Nagle算法与TCP_NODELAY
TCP 有一个数据流接口,应用程序可以通过它将任意尺寸的数据放入 TCP 栈中—— 即使一次只放一个字节也可以!但是,每个 TCP 段中都至少装载了 40 个字节的标 记和首部,所以如果 TCP 发送了大量包含少量数据的分组,网络的性能就会严重 下降。
Nagle 算法(根据其发明者 John Nagle 命名)试图在发送一个分组之前,将大量 TCP 数据绑定在一起,以提高网络效率。RFC 896“IP/TCP 互连网络中的拥塞控 制”对此算法进行了描述。
Nagle 算法鼓励发送全尺寸(LAN 上最大尺寸的分组大约是 1500 字节,在因特网 上是几百字节)的段。只有当所有其他分组都被确认之后,Nagle 算法才允许发送 非全尺寸的分组。如果其他分组仍然在传输过程中,就将那部分数据缓存起来。只 有当挂起分组被确认,或者缓存中积累了足够发送一个全尺寸分组的数据时,才会 将缓存的数据发送出去。
Nagle 算法会引发几种 HTTP 性能问题。首先,小的 HTTP 报文可能无法填满一个 分组,可能会因为等待那些永远不会到来的额外数据而产生时延。其次,Nagle 算 法与延迟确认之间的交互存在问题——Nagle 算法会阻止数据的发送,直到有确认 分组抵达为止,但确认分组自身会被延迟确认算法延迟 100 ~ 200 毫秒。
HTTP 应用程序常常会在自己的栈中设置参数 TCP_NODELAY
,禁用 Nagle 算法, 提高性能。如果要这么做的话,一定要确保会向 TCP 写入大块的数据,这样就不会 产生一堆小分组了。
串行事务处理时延
并行连接
通过多条TCP连接发起并发的HTTP请求。持久连接
重用TCP连接,以消除连接及关闭时延。管道化连接
通过共享的TCP连接发起并发的HTTP请求。复用的连接
交替传送请求和响应报文(试验阶段)。
集成点:网关、隧道及中继
网关
- 协议网关
- HTTP/*:服务器端Web网关
- HTTP/HTTPS:服务器端安全网关
- HTTPS/HTTP客户端安全加速器网关
- 资源网关
- CGI (Common Gateway Interface,CGI)
通用网关接口,CGI是一个标准接口集,Web服务器可以用它来装载程序以响应对特对URL的HTTP请求,并收集程序的输出数据,将其放在HTTP响应中回送。
CGI应用程序是独立于服务器的,所以,几乎可以用任意语言来实现,包括Perl、Tcl、C和各种shell语言。
它在服务器和众多的资源类型 之间提供了一种简单的、函数形式的粘合方式,用来处理各种需要的转换。这个接 口还能很好地保护服务器,防止一些糟糕的扩展对它造成的破坏(如果这些扩展直 接与服务器相连,造成的错误可能会引发服务器崩溃)。 但是,这种分离会造成性能的耗费。为每条 CGI 请求引发一个新进程的开销是很高 的,会限制那些使用 CGI 的服务器的性能,并且会加重服务端机器资源的负担。为 了解决这个问题,人们开发了一种新型 CGI——并将其恰当地称为快速 CGI。这个 接口模拟了 CGI,但它是作为持久守护进程运行的,消除了为每个请求建立或拆除 新进程所带来的性能损耗。
- CGI (Common Gateway Interface,CGI)
隧道
Web隧道允许用户通过HTTP连接发送非HTTP流量,这样就可以在HTTP上捎带其他协议数据了。
用CONNECT建立HTTP隧道
CONNECT请求:除了起始行之外,CONNECT的语法与其他HTTP方法类似。主机和端口都必须指定:
1 | CONNECT home.netscape.com:443 HTTP/1.0 |
CONNECT响应:按照惯例,响应中的原因短语通常被设置为Connection Established
:
1 | HTTP/1.0 200 Connection Established |
与普通HTTP响应不同,这个响应并不需要包含Content-Type
首部。此时连接至是对原始字节进行转接,不再是报文的承载者,所以不需要使用内容类型了。
中继
HTTP中继(relay)是没有完全遵循HTTP规范的简单HTTP代理。中继负责处理HTTP中建立连接的部分,然后对字节进行盲转发。
HTTP 很复杂,所以实现基本的代理功能并对流量进行盲转发,而且不执行任何首 部和方法逻辑,有时是很有用的。盲中继很容易实现,所以有时会提供简单的过滤、 诊断或内容转换功能。但这种方式可能潜在严重的互操作问题,所以部署的时候要 特别小心。
某些简单盲中继实现中存在的一个更常见(也更声名狼藉的)问题是,由于它们无 法正确处理 Connection 首部,所以有潜在的挂起 keep-alive 连接的可能。
安全HTTP
HTTPS
大部分困难的编码及解码工作都是在 SSL 库中完成的,所以 Web 客户端和服务器 在使用安全 HTTP 时无需过多地修改其协议处理逻辑。在大多数情况下,只需要用 SSL 的输入 / 输出调用取代 TCP 的调用,再增加其他几个调用来配置和管理安全信 息就行了。
数字加密
基本概念:
- 密码
对文本进行编码,使偷窥者无法识别的算法。 - 密钥
改变密码行为的数字化参数。 - 对称密钥加密系统
编/解码使用相同密钥的算法。 - 不对称密钥加密系统
编/解码使用不同密钥的算法。 - 公开密钥加密系统
一种能够使数百万计算机便捷地发送机密报文的系统。 - 数字签名
用来验证报文未被伪造或篡改的校验和。 - 数字认证
由一个可信的组织验证和签发的识别信息。
HTTPS方案
SSL 是个二进制协议,与 HTTP 完全不同,其流量是承载在另一个端口上的(SSL 通常是由端口 443 承载的)。如果 SSL 和 HTTP 流量都从端口 80 到达,大部分 Web 服务器会将二进制 SSL 流量理解为错误的 HTTP 并关闭连接。将安全服务进一步整 合到 HTTP 层中去就无需使用多个目的端口了,在实际中这样不会引发严重的问题。
站点证书的有效性
SSL自身不要求用户检查Web服务器证书,但大部分现代浏览器都会对证书进行简单的完整性检查,并为用户提供进行进一步彻查的手段。网景公司提出的一种Web服务器证书有效性算法是大部分浏览器有效性验证技术的基础。验证步骤如下所述:
- 日期检测
- 签名颁发者可信度检测
- 签名检测
- 站点身份检测
OpenSSL
OpenSSL是SSL和TLS最常见的开源实现。OpenSSL项目由一些志愿者合作开发,目标是开发一个强壮的、具有完备功能的商业级工具集,以实现SSL和TLS协议以及一个全功能的通用加密库。
通过代理以隧道形式传输安全流量
客户端通常会用 Web 代理服务器(参见第 6 章)代表它们来访问 Web 服务器。比 如,很多公司都会在公司网络和公共因特网的安全边界上放置一个代理(参见图 14-19)。代理是防火墙路由器唯一允许进行 HTTP 流量交换的设备,它可能会进行 病毒检测或其他的内容控制工作。但一旦客户端开始用服务器的公开密钥对发往服务器的数据进行加密,代理无法转发加密请求。
为了使HTTPS与代理配合工作,要进行几处修改以告知代理连接到何处。一种常用的技术就是HTTPS SSL隧道协议。 使用 HTTPS 隧道协议,客户端首先要告知代 理,它想要连接的安全主机和端口。这是在开始加密之前,以明文形式告知的,所 以代理可以理解这条信息。