第二部分:HTTP结构
第5章 Web服务器
第一步 接受客户端连接
如果客户端已打开一条到服务器的持久连接,可以使用那条连接来发送它的请求。否则客户端需要打开一条新的服务器的连接。
处理新连接
客户端请求一条到 Web 服务器的 TCP 连接时,Web 服务器会建立连接,从 TCP 连接中将 IP 地址解析出来。若新连接建立,服务器就会将新连接添加到其现存 Web 服务器连接列表中,做好监视连接上数据传输的准备。
客户端主机名识别
Web 使用“反向 DNS”,将客户端 IP 地址转换成客户端主机名,用于详细的访问控制和日志记录。但这样会降低 Web 事务处理的事务,所以很多大容量 Web 服务器要么会禁止主机名解析,要么只允许对特定内容进行解析。
通过ident确定客户端用户
第二步 接收请求报文
解析请求报文
解析请求报文时,Web 服务器会:
- 解析请求行,查找请求方法、指定URI、版本号,各项由空格隔开,并以 CRLF 结束。
- 读取以 CRLF 结尾的报文首部。
- 检测到以 CRLF 结尾的空行(如果有的话)。
- 读取请求主体(如果有的话,长度由 Content-Length 首部指定)。
连接的输入/输出处理结构
- 单线程 Web 服务器:单进程处理完一个请求后,才去处理下一个连接。
- 多进程及多进程 Web 服务器:多个进程同时对请求进行处理。
- 复用 I/O 的服务器:同时监视所有连接上的活动,当连接状态改变时,才做处理。处理结束后,将连接返回到开放连接列表中,等待下一次状态的变化。
- 复用的多线程 Web 服务器:每个线程都在观察打开的连接,并对每条连接执行少量的任务。
第三步 处理请求
第四步 对资源的映射及访问
第五步 构建响应
当 Web 服务器识别出了资源,就执行请求方法中描述的动作,并返回响应报文。
第六步 发送响应
服务器要记录连接的状态。对非持久连接,服务器发送了整条报文后,关闭自己这一端的连接;对持久连接则要正确计算 Content-Length 首部,确保让客户端知道响应是否结束。
第七步 记录日志
当食物结束时,Web 服务器会在日志文件中添加一个条目,来描述已执行的事务。
第6章 代理
Web的中间实体
Web 上的代理服务器是代表客户端完成事务处理的中间人。既是 Web 服务器又是 Web 客户端。
私有和共享代理
- 公共代理:多个客户端共享,集中式代理的费效比更高、更容易管理。
- 私有代理:单个客户端专用,以便扩展浏览器特性、提高性能。
代理与网关的对比
代理连接的是两个或多个使用相同协议的应用程序,而网关连接的则是两个或多个使用不同协议的端点。
代理使用示例
- 儿童过滤器
- 文档访问控制
- 安全防火墙
- Web 缓存
- 反向代理:代理假扮 Web 服务器。
- 匿名者
代理部署
部署代理的方式
出口代理
可以将代理固定在本地网络的出口点,以便控制本地网络与大型因特网之间的流量。
访问(入口)代理
代理常被放在 ISP 访问点上,以处理来自客户的聚合请求。ISP 使用缓存代理来存储常用文档的副本,以提高用户的下载速度。
反向代理
代理通常会被部署在网络边缘,在 Web 服务器之前,作为替代物使用,在那里它们可以处理所有传送给 Web 服务器的请求,并只在必要时向 Web 服务器请求资源。
网络交换代理
可以将具有足够处理能力的代理放在网络之间的因特网对等交换点上,通过缓存来减轻因特网节点的拥塞,并对流量进行监视。
代理的层次结构
代理层次结构可以是动态的,随请求而变的。
动态选择父代理的例子:
- 负载均衡:子代理根据当前父代理上的工作负载级别来决定如何选择一个父代理,以均衡负载。
- 地理位置附近的路由:子代理会选择负责原始服务器所在物理区域的父代理。
- 协议/类型路由:子代理根据 URI 将报文转发到不同的父代理和原始服务器上去。
- 基于订购的路由
代理是如何获取流量的
- 修改客户端:对浏览器进行手工和自动的代理配置。
- 修改网络:监视 HTTP 流量的交换设备及路由设备拦截网络流量并将其导入代理(又称为拦截代理)。
- 修改 DNS 的命名空间:手工编辑 DNS 名称列表,或者用特殊的动态 DNS 服务器根据需要来确定适当的代理或服务器。
- 修改 Web 服务器:将 Web 服务器配置为向客户端发送一条 HTTP 重定向命令(305),将请求重定向到一个代理上去。
客户端的代理设置
- 手工配置:显示设置要使用的代理。
- 预先配置浏览器:浏览器厂商对浏览器的代理设置进行手工配置。
- 代理的自动配置(PAC):客户端指定 URI 读取一个用 Js 编写的代理自动配置文件,并运行它来决定是否应该使用一个代理。
- WPAD 的代理发现:Web 代理自动发现协议会自动检测出浏览器可以从哪个“配置服务器”下载到自动配置文件。
第7章 缓存
冗余的数据传输
缓存可以保存第一条服务器相应的副本,应付后续的请求。
带宽瓶颈
很多网络为本地网络客户端提供的带宽比远程服务器提供的带宽宽。如果客户端从一个快速局域网的缓存中得到一份副本,那么缓存就可以提高性能。
瞬间拥塞
很多人几乎同时去访问一个 Web 文档时,就会出现瞬间拥塞。缓存在破坏瞬间拥塞时显得非常重要。
距离时延
每台网络路由器都会增加因特网流量的时延,即使没有太多的路由器,光速自身也会造成显著的时延。
命中和未命中
可以用已有的副本为某些到达缓存的请求提供服务,称为缓存命中。其他到达缓存的请求可能由于没有副本可用,而被转发给原始服务器,称为缓存未命中。
再验证
原始服务器的内容可能会发生变化,缓存要不时对其进行检测,看看它们保存的副本是否仍是服务器上最新的副本。这种“新鲜度检测”称为 HTTP 再验证。
命中率
由缓存提供服务的请求所占的比例被称为缓存命中率。
缓存的拓扑结构
单个用户专用的缓存称为私有缓存,共享的缓存称为公有缓存。
私有缓存
Web 浏览器中有内建的私有缓存——大多数浏览器会将常用文档缓存在你个人电脑的磁盘和内存中,并且允许用户去配置缓存的大小和各种设置。
公有代理缓存
公有缓存是特殊的共享代理服务器,被称为缓存代理服务器或代理缓存。
代理缓存的层次结构
层次化的缓存结构中,在较小缓存未命中的请求会被导向较大的父缓存,由它来为剩下的那些“提炼过的”流量提供服务。
网状缓存、内容路由以及对等缓存
- 网状缓存:比层次结构的缓存复杂。
- 内容路由:网状缓存中的代理缓存之间会以更复杂的方式进行对话,做出动态的缓存通信决策,决定与哪个父缓存进行对话,或决定彻底绕开缓存直接连接原始服务器。
- 对等:缓存之间的关系允许不同的组织互为对等实体,将它们的缓存连接起来以实现共赢。
缓存的处理步骤
- 接收——缓存从网络中读取抵达的请求报文。
- 解析——缓存对报文进行解析,提取出 URL 和各种首部。
- 查询——缓存查看是否有本地副本可用,如果没有,就获取一份副本,并将其保存在本地。
- 新鲜度检测——缓存查看已缓存副本是否足够新鲜,若不是则询问服务器是否有任何更新。
- 创建响应——缓存会用新的首部和已缓存的主体来构建一条响应报文。
- 发送——缓存通过网络将响应发回给客户端。
- 日志——缓存可选地创建一个日志文件条目来描述这个事务。
保持副本的新鲜
文档过期和服务器再验证:可以在不要求服务器记住有哪些缓存拥有其文档副本的情况下,保持已缓存数据与服务器数据充分一致。
文档过期
通过 Cache-Control 和 Expires 首部,HTTP 让原始服务器向每个文档附加了一个“过期日期”,这些首部说明了在多长时间内可以将这些内容视为新鲜的。
Cache-Control: max-age
max-age 值定义了文档的最大使用期
Expires: 日期
指定一个绝对的过期日期,如果过期时间已经过了,说明文档不再新鲜了。
服务器再验证
文档过期意味着缓存到了要进行核对的时间,缓存需要询问原始服务器文档是否发生了变化。
- 如果再验证显示内容发生了变化,缓存会获取一份新的副本,然后将文档发送给客户端。
- 如果再验证显示内容没有发生变化,缓存只需要获取新的首部(过期日期),更新缓存中的首部。
控制缓存的能力
服务器可以通过 HTTP 定义的几种方式来指定在文档过期之间可以将其缓存多长时间。按照优先级递减的顺序,服务器可以:
- Cache-Control: no-store
- Cache-Control: no-cache
- Cache-Control: must-revalidate
- Cache-Control: max-age
- Expires: 绝对日期
- 不附加过期日期,让缓存自己确定
no-store 与 no-cache
防止缓存提供未经证实的已缓存对象。
- no-store:禁止缓存对响应进行复制。
- no-cache:在与原始服务器进行新鲜度再验证之前,缓存不能将其提供给客户端使用。
must-revalidate
告诉缓存,在事先没有跟原始服务器进行再验证的情况下,不能提供这个对象的陈旧副本。
max-age
表示从服务器将文档传来之时起,可以认为此文档处于新鲜状态的秒数。
Expires
不推荐使用,它指定的是实际的过期日期而不是秒数。
第8章 集成点:网关、隧道及中继
网关
网关抽象出一种能够到达资源的方法,是资源和应用程序之间的粘合剂。
三个 Web 网关实例:
协议网关
HTTP/*:服务器端Web网关
请求流入原始服务器,服务器端 Web 网关会将客户端 HTTP 请求转换为其他协议。
HTTP/HTTPS:服务器端安全网关
一个组织可以通过对所有的输入 Web 请求加密,以提供额外的隐私和安全性保护。
资源网关
常见的网关——应用程序服务器,会将目标服务器将网关结合在一个服务器中实现,是服务器端网关,与客户端通过 HTTP 进行通信,并与服务器端的应用程序相连。
CGI
CGI 应用程序是独立于服务器的,几乎所有 HTTP 服务器都支持它。它在服务器和众多的资源类型之间提供了一种简单的、函数形式的粘合方式,用来处理各种需要的转换。这个接口还能很好地保护服务器,防止一些扩展破坏服务器。
隧道
HTTP 除了通过网关对不同类型的资源进行访问,还可以通过隧道来访问非 HTTP 协议的应用程序。
Web 隧道运行用户通过 HTTP 连接来发送非 HTTP 流量,这样就可以在 HTTP 上捎带其他协议的数据了。使用 Web 隧道最常见的原因就是要在 HTTP 连接中嵌入非 HTTP 流量,这样这类流量就可以穿过只允许 Web 流量的防火墙了。
用CONNECT建立HTTP隧道
CONNECT方法请求隧道网关创建一条到达任意目的服务器和端口的 TCP 连接,并对客户端和服务器之间的后继数据进行盲转发。
CONNECT 请求
CONNECT home.xxx.com:443 HTTP/1.0
CONNECT 响应
HTTP/1.0 200 Connection Established
示例:
- (a)客户端发送一条 CONNECT 请求给隧道网关。客户端请求隧道网关打开一条 TCP 连接(打开到主机 orders 主机的标准 SSL端口 443 的连接)。
- (b)(c)创建 TCP 连接。
- (d)当建立了 TCP 连接,网关会发送 HTTP 200 Connection Established 响应通知客户端。
- 隧道建立起来后,客户端通过 HTTP 隧道发送的所有数据都会被直接转发输出 TCP 连接,服务器发送的所有数据都会通过 HTTP 隧道转发给客户端。
SSL隧道
加密 SSL 的信息是加密的,无法通过传统的代理服务器转发,所以为了通过防火墙来传输加密的 SSL 流量,隧道会通过一条 HTTP 连接来传输 SSL 流量,以穿过端口 80 的 HTTP 防火墙。
- (a)SSL 流量被直接发送给了一个安全 Web 服务器(SSL 端口 443 上的)。
- (b)SSL 流量被封装到一条 HTTP 报文中,并通过 HTTP 端口 80 上的连接发送,最后被解封装为普通的 SSL 连接。
中继
HTTP 中继是没有完全遵循 HTTP 规范的简单 HTTP 代理,负责处理 HTTP 中建立连接的部分,不执行任何首部和方法逻辑,然后对字节进行盲转发。
第9章 Web机器人
暂无笔记。
第10章 HTTP-NG
暂无笔记。