Oh!Coder

Coding Life

读《HTTP权威指南》笔记(二)

| Comments

本书的第二部分主要讨论了HTTP的结构。其中主要包括HTTP服务器、代理、网关和机器人应用程序,基本上这些都是Web系统架构的构造模块。这部分的章节比较多,一共分为了六个章节。下面还是按照每个章节进行总结。

第五章:Web服务器

开篇先是整体介绍了不同类型的Web服务器。分别从服务器的软件和硬件进行了介绍。软件方面介绍了一些市面上常见的服务器厂商,包括了三家(Page.117):

  • 免费的Apache软件
  • 微软的Web服务器
  • Sun的iPlanet

随后展示了一个用Perl实现的Web服务器的例子,并对代码的工作流程做了简要的说明。接下来本章的主线都是围绕Web服务器所完成的操作展开(Page.120~Page.121)。

(1)建立连接——接受一个客户端连接,或者如果不希望与这个客户端建立连接,就将其关闭。
(2)接收请求——从网络中读取一条HTTP请求报文。
(3)处理请求——对请求报文进行解释,并采取行动。
(4)访问资源——访问报文中指定的资源。
(5)构建响应——创建带有正确首部的HTTP响应报文。
(6)发送响应——将响应回送给客户端。
(7)记录事务处理过程——将与已完成事务有关的内容记录在一个日至文件中。

下面我们逐条进行说明。

第一步——接受客户端连接

在这个步骤中,包括建立连接,这里Web服务器可以随意拒绝或立即关闭任意一条连接。客户端主机名解析部分,服务器可以用“反向DNS”对大部分Web服务器进行配置,Web服务器可以将客户端主机名用于详细的访问控制和日志记录。通过ident确定客户端用户,如果客户端支持ident协议,就在TCP端口113上监听ident请求。ident在组织内部可以很好地工作,但出于多种原因,在公共因特网上并不能很好地工作,原因包括:

  • 很多客户端PC没有运行ident识别协议守护进程软件;
  • ident协议会使HTTP事务处理产生严重的时延;
  • 很多防火墙不允许ident流量进入;
  • ident协议不安全,容易被伪造;
  • ident协议也不支持虚拟IP地址;
  • 暴露客户端的用户名还涉及隐私问题。

第二步——接收请求报文

解析请求报文时,Web服务器会不定期地从网络上接收输入数据。网络连接可能随时都会出现延迟。Web服务器需要从网络中读取数据,将部分报文数据临时存储在内存中,直到收到足以进行解析的数据并理解其意义为止。在连接的输入/输出处理结构部分,描述了不同的Web服务器会以不同的方式为请求服务(Page.125):

  • 单线程Web服务器。单线程的Web服务器一次只处理一个请求,直到完成为止。
  • 多进程及多线程Web服务器。多进程和多线程Web服务器用多个进程,或更高效的线程同时对请求进行处理。但是,很多多线程Web服务器都会对线程/进程的最大数量进行限制。
  • 复用I/O的服务器。为支持大量的连接,很多Web服务器都采用了复用结构。对于复用的服务器,只有在有事情可做时才会对连接进行处理;在空闲连接上等待的时候并不会绑定线程和进程。
  • 复用的多线程Web服务器。有些系统会将多线程和复用功能结合在一起,以利用计算机平台上的多个CPU。

第三步——处理请求

有些方法(比如POST)要求报文中必须带有实体主体部分的数据。其他一些方法(比如OPTIONS)允许有请求的主体部分,也允许没有。少数方法(比如GET)禁止请求报文中包含实体的主体数据。

第四步——对资源的映射及访问

对于资源的映射部分,讲到了文档的根目录(document root,或docroot)。对于文档的根目录包括了两种类型的目录。一种是虚拟托管的docroot。文中用Apache中关于docroot的配置方法做为讲解示例进行了介绍。第二种是用户的主目录docroot。这种应用是在Web服务器上为人们提供私有的Web站点。通常会把那些以斜杠和波浪号(/~)开始,后面跟着用户名的URI映射为此用户的私有文档根目录。关于第二种主目录,在最新的Mac系统下,如果你试着为当前登陆用户配置一下系统中默认的Apache,会有更直观的理解。

第五步——构建响应

一旦Web服务器识别出了资源,就执行请求方法中描述的动作,并返回响应报文。响应报文中包含有响应状态码、响应首部,如果生成了响应主体的话,还包括响应主体。如果事务处理产生了响应主体,就将内容放在响应报文中回送过去。如果有响应主体的话,响应报文中通常包括:

  • 描述了响应主体MIME类型的Content-Type首部;
  • 描述了响应主体长度的Content-Length首部;
  • 实际报文的主体内容。

Web服务器要负责确定响应主体的MIME类型(Page.132~Page.133)。

  • MIME类型。Web服务器可以用文件的扩展名来说明MIME类型。这种基于扩展名的类型相关是最常见的。
  • 魔法分类。Apache Web服务器可以扫瞄每个资源的内容,并将其与一个已知模式表(被称为魔法文件)进行匹配,以决定每个文件的MIME类型。
  • 显示分类。可以对Web服务器进行配置,使其不考虑文件的扩展名或内容,强制特定文件或目录内容拥有某个MIME类型。
  • 类型协商。有些Web服务器经过配置,可以以多种文档格式来存储资源。

对于Web服务器返回重定向响应来说,重定向可用于下列情况(Page.133)。

  • 永久删除的资源
  • 临时删除的资源
  • URL增强
  • 负载均衡
  • 服务器关联
  • 规范目录名称

第六步——发送响应

对非持久连接而言,服务器应该在发送了整条报文之后,关闭自己这一端的连接。对持久连接来说,连接可能仍保持打开状态,在这种情况下,服务器要特别小心,要正确地计算Content-Length首部,不然客户端就无法知道响应什么时候结束了。

第七步——记录日至

最后,当事务结束时,Web服务器会在日志文件中添加一个条目,来描述已执行的失去。

第六章:代理

本章一开始介绍了一下Web代理的概念(Page.136)。

Web上的代理服务器是代表客户端完成事务处理的中间人。

另外,HTTP的代理服务器是Web服务器又是Web客户端。

为什么使用代理呢?书中给出了几种代理使用方法的示例(Page.138~Page.142)。

  • 儿童过滤器
  • 文档访问控制
  • 安全防火墙
  • Web缓存
  • 反响代理
  • 内容路由器
  • 转码器
  • 匿名者

简单介绍几个上面提到的示例。

Web缓存(Page.140),代理缓存维护了常用文档的本地副本,并将它们按需提供,以减少缓慢且昂贵的因特网通信。

反向代理(Page.140),代理可以假扮Web服务器。这些被称为替代物(surrogate)或反向代理(reverse proxy)的代理接收发给Web服务器的真实请求。

内容路由器(Page.141),代理服务器可以作为“内容路由器”使用,根据因特网流量状况以及内容类型将请求导向特定的Web服务器。

转码器(Page.141),代理服务器在将内容发送给客户端之前,可以修改内容的主体格式。在这些表示法之间进行的透明转换被称为转码(transcoding)。

文中给出了几种代理服务器的部署方式(Page.144)。

  • 出口代理。可以将代理固定在本地网络的出口点,以便控制本地网络与大型因特网之间的流量。
  • 访问(入口)代理
    代理常被放在ISP访问点上,用以处理来自客户的聚合请求。
  • 反向代理
    代理通常会被部署在网络边缘,在Web服务器之前,作为替代物(也常被称为反向代理)使用,在那里它们可以处理所有传送给Web服务器的请求,并只在必要时间向Web服务器请求资源。

  • 网络交换代理
    可以将具有足够处理器能力的代理放在网络之间的因特网对等交换点上,通过缓存来减轻因特网节点的拥塞,并对流量进行监视。

另外,可以通过代理层次结构(proxy hierarchy)将代理级联起来。Proxy层次结构中的代理服务器被赋予了父(parent)和子(child)的关系。下一个入口(inbound)代理(靠近服务器)被称为父代理,下一个出口(outbound)代理(靠近客户端)被称为子代理。

客户端的代理设置方面,书中提到了几种方式(Page.148~Page.149)。

  • 手工配置。显示地设置要使用的代理。
  • 预先配置浏览器。
  • 代理的自动配置(Proxy Auto-Configuration, PAC)。提供一个URI,只想一个用JavaScript语言编写的代理自动配置文件;客户端会取回这个JavaScript文件,并运行它以决定是否应该使用一个代理,如果是的话,应该使用哪个代理服务器。
  • WPAD的代理发现。有些浏览器支持Web代理自动发现协议(Web Proxy Autodiscovery Protocol,WPAD),这个协议会自动检测出浏览器可以从哪个“配置服务器”下载到一个自动配置文件。

对于代理URI与服务器URI,在客户端进行访问的时候还是有一些不同的。客户端向Web服务器发送请求时,请求行中只包含部分URI。但当客户端向代理发送请求时,请求行中则包含完整的URI。不过,书中说目前HTTP/1.1要求服务器为代理请求和服务器请求都提供完整的URI处理,但实际上,很多已部署的服务器仍然只接受部分URI。

随后书中对有显式代理或拦截代理时的URI解析步骤做了简要的介绍。

Via首部

在通用首部字段类型中,Via首部字段列出了与报文途径的每个中间节点(代理或网关)有关的信息。报文每经过一个节点,都必须将这个中间节点添加到Via列表的末尾。Via首部字段用于记录报文的转发,诊断报文循环,标识请求/响应链上所有发送者的协议能力。

代理可以用Via首部来检测网络中的路由循环。

Via的语法

Via首部字段包含一个由逗号分隔的路标(waypoint)。每个路标都表示一个独立的代理服务器或网关,且包含与那个中间节点的协议和地址有关的信息。这里列举一个书上的Via首部实例:

Via = 1.1 cache.joes-hardware.com, 1.1 proxy.irense-isp.net

Via首部的正规语法如下:

Via = "Via" ":" 1#(waypoint) waypoint = (received-protocol received-by[comment]) received-protocol = [protocol-name "/"] protocol-version received-by = (host[":" port]) | pseudonym

每个Via路标中最多包含4个组件:一个可选的协议名(默认为HTTP)、一个必选的协议版本、一个必选的节点名和一个可选的描述性注释。

请求和响应报文都会经过代理传输,因此,请求和响应报文中都要有Via首部。

Trace方法

(Page.163)通常,不管中间插入了多少代理,TRACE报文都会沿着整条路径传到目的服务器上。

代理认证

HTTP定义了一种名为代理认证(proxy authentication)的机制,这种机制可以阻止对内容的请求,直到用户向代理提供了有效的访问权限证书为止。

第七章:缓存

本章主要介绍了网络中的缓存。对于缓存的优点,书中给出了几点(Page.170):

  • 缓存减少了冗余的数据传输。
  • 缓存缓解了网络瓶颈的问题。
  • 缓存降低了对原始服务器的要求。
  • 缓存降低了距离时延。

(Page.173)可以用已有的副本为某些到达缓存的请求提供服务。这被称为缓存命中(cache hit)。其他一些到达缓存的请求可能会由于没有副本可用,而被转发给原始服务器。这被称为缓存未命中(cache miss)

(Page.175)由缓存提供服务的请求所占的比例被称为缓存命中率(cache hit rate,或称为缓存命中比例),有时也被称为文档命中率(document hit rate)

缓存根据用户的使用方式分为私有缓存(private cache)和公有缓存(public cache)。(Page.177)专用缓存被称为私有缓存(private cache)。私有缓存是个人的缓存,包含了单个用户最常用的页面。共享的缓存被称为公有缓存(public cache)。公有缓存中包含了某个用户团体的常用页面。

对于缓存处理的步骤包括(Page.182):

  1. 接收——缓存从网络中读取抵达的请求报文。
  2. 解析——缓存对报文进行解析,提取出URL和各种首部。
  3. 查询——缓存查看是否有本地副本可用,如果没有,就获取一份副本(并将其保存在本地)。
  4. 新鲜度检测——缓存查看已缓存副本是否足够新鲜,如果不是,就询问服务器是否有任何更新。
  5. 创建响应——缓存会用新的首部和已缓存的主体来构建一条响应报文。
  6. 发送——缓存通过网络将响应发回给客户端。
  7. 日志——缓存可选地创建一个日志文件条目来描述这个事务。

HTTP定义了5个条件请求首部。对缓存再验证来说最有用的2个首部是If-Modified-SinceIf-None-Match

服务器可以通过HTTP定义的几种方式来指定在文档过期之前可以将其缓存多长时间。按照优先级递减的顺序,服务器可以:

  • 附加一个Cache-Control:no-store首部到响应中去;
  • 附加一个Cache-Control:no-cache首部到响应中去;
  • 附加一个Cache-Control:must-revalidate首部到响应中去;
  • 附件一个Cache-Control:max-age首部到响应中去;
  • 附加一个Expires日期首部到响应中去;
  • 不附加过期信息,让缓存确定自己的过期日期。

本章接下来对文档的新鲜和过期算法进行了介绍,并通过一段简单的Perl代码进行了说明。

整体来看,这一章内容都是在围绕着代理的功能进行描述的,这一章的内容很多,知识点感觉也比较杂。

第八章:网关

什么是网关?(Page.208)网关是资源和应用程序之间的粘合剂。

接下来介绍了两类网关,一类是协议网关,另一类是资源网关。

协议网关

对于协议网关,常见的网关类型有(Page.211):服务器协议转换器、服务器端安全网关、客户端安全网关以及应用程序服务器。

  • 服务器端Web网关(Page.211)
    请求流入原始服务器时,服务器端Web网关会将客户端HTTP请求转换为其他协议。

  • 服务器端安全网关(Page.212)
    一个组织可以通过网关对所有的输入Web请求加密,以提供额外的隐私和安全性保护。

  • 客户端安全加速器网关(Page.212)
    这些HTTPS/HTTP网关位于Web服务器之前,通常作为不可见的拦截网关或反向代理使用。它们接收安全的HTTPS流量,对安全流量进行解密,并向Web服务器发送普通的HTTP请求。

资源网关

最常见的网关,应用程序服务器,会将目标服务器与网关结合在一个服务器中实现。应用程序网关是服务器端网关,与客户端通过HTTP进行通信,并与服务器端的应用程序相连。

第一个流行的应用程序网关API就是通用网关接口(Common Gateway Interface,CGI)。CGI是一个标准接口集,Web服务器可以用它来装载程序以响应对特定URL的HTTP请求,并收集程序的输出数据,将其放在HTTP响应中回送。

隧道

Web隧道(Web tunnel),这种方式可以通过HTTP应用程序访问使用非HTTP协议的应用程序。Web隧道允许用户通过HTTP连接发送非HTTP流量,这样就可以在HTTP上捎带其他协议数据了。使用Web隧道最常见的原因就是要在HTTP连接中嵌入非HTTP流量,这样,这类流量就可以穿过只允许Web流量通过的防火墙了。

Web隧道是用HTTP的CONNECT方法建立起来的。CONNECT方法并不是HTTP/1.1核心规范的一部分,但却是一种得到广泛应用的扩展。

对于管道化数据而言,是不透明的,所以网关不能对分组的顺序和分组流作任何假设。一旦隧道建立起来,数据就可以在任意时间流向任意方向了。

CONNECT请求的语法与其他HTTP方法类似,但主机和端口都必须指定(Page.218):
CONNECT home.netscape.com:443 HTTP/1.0 User-agent:Mozilla/4.0

CONNECT响应和普通的HTTP报文一样,响应码200表示成功(Page.219)。

HTTP/1.0 200 Connection Established Proxy-agent: Netscape-Proxy/1.1

SSL隧道

最初开发Web隧道是为了通过防火墙来传输加密的SSL流量的。此处描述了两种用SSL传输数据的方式。一种是直接在客户端和终端服务器上建立SSL连接,以提高数据传输的安全性,另一种是通过一条HTTP连接来传输SSL流量,以穿过端口80的HTTP防火墙。

中继

HTTP中继(relay)是没有完全遵循HTTP规范的简单HTTP代理。中继负责处理HTTP中建立连接的部分,然后对字节进行盲转发。

第九章:Web机器人

对于Web机器人,书中还介绍了一些其他名字,例如“爬虫”、“蜘蛛”、“蠕虫”以及“机器人”等。对Web爬虫的定义,书中做了一段比较形象的描述。(Page.226)Web爬虫是一种机器人,它们会递归地对各种信息性Web站点进行遍历,获取第一个Web页面,然后获取那个页面指向的所有Web页面,然后是那些页面指向的所有Web页面,依此类推。递归地追踪这些Web链接的机器人会沿着HTML超链创建的网络“爬行”,所以将其称为爬虫(crawler)蜘蛛(spider)

(Page.226)爬虫开始访问的URL初始集合被称作根集(root set)。机器人在Web上爬行时,需要特别小心不要陷入循环,或环路(cycle)之中。书中列出了三种循环对爬虫有害的原因(Page.228)。

  • 它们会使爬虫陷入可能会将其困住的循环之中。
  • 爬虫不断地获取相同的页面时,另一端的Web服务器也在遭受着打击。
  • 即使循环自身不是什么问题,爬虫也是在获取大量重复的页面[通常被称为“dups”(重复),以便与“loops”(循环)押韵]。

书中展示了几种对于大规模Web爬虫对其访问过的地质进行管理时使用的一些有用的技术(Page.229)。

  • 树和散列表
    复杂的机器人可能会用搜索树或散列表来记录已访问的URL。这些是加速URL查找的软件数据结构。
  • 有损的存在位图
    为了减小空间,一些大型爬虫会使用有损数据结构,比如存在位数组(presence bit array)。
  • 检查点
    一定要将已访问URL列表保存到硬盘上,以防机器人程序崩溃。
  • 分类

对于别名的概念,书中给出了简单概念,(Page.230)如果两个URI看起来不一样,但实际指向的是同一资源,就称这两个URL互为“别名”。对于避免机器人环路的问题,书中提出了规范化URL格式的办法。虽然URL规范化可以消除一些基本的语法别名,但机器人还会遇到其他的,将URL转换为标准形式也无法消除的URL别名。

总的来说,爬虫的自动化程度越高(人为的监管越少),越可能陷入麻烦之中。为了避免机器人遇到各种危险,书中给出了一些技术方案(Page.233)。

  • 规范化URL
  • 广度优先的爬行
  • 节流
  • 限制URL的大小
  • URL/ 站点黑名单
  • 模式检测
  • 内容指纹
  • 人工监视

当然了,除了这些防止机器人遇到各种危险的措施以外,也会有一些行为不当的机器人,例如(Page.239),

  • 失控机器人
  • 失控的URL
  • 很长的错误URL
  • 爱打听的机器人
  • 动态网关访问

拒绝机器人访问标准有三个版本(Page.242),

  • 版本0.0
    拒绝机器人标准——(1994年6月)Martijn Koster提出的带有Disallow(不允许)指令的原始robots.txt机制。
  • 版本1.0
    控制Web机器人的方法——(1996年11月)Martijn Koster提供了额外支持Allow(允许)的IETF草案。
  • 版本2.0
    拒绝机器人访问的扩展标准——(1996年11月)Sean Conner提出的扩展标准,包括了正则表达式和定时信息,没有得到广泛的支持。

如果一个Web站点有robots.txt文件,那么在访问这个Web站点上的任意URL之前,机器人都必须获取它并对其进行处理。

robots.txt文件中有三种类型的行:空行、注释行和规则行。规则行看起来就像HTTP首部一样,用于模式匹配。比如(Page.243),

\# this robots.txt file allows Slurp & Webcrawler to crawl \# the public parts of our site. but no other robots... User-Agent: slurp User-Agent: webcrawler Disallow: /private

User-Agent: *
Disallow: </code>

User-Agent行

每个机器人记录都以一个或多个下列形式的User-Agent行开始:

User-Agent: \<robot-name\>

User-Agent: *

  • 第一个<robot-name>是机器人名的大小写无关的子字符串;
  • 第一个<robot-name>为“*”
Disallow和Allow行

Disallow和Allow行紧跟在机器人排斥记录的User-Agent行之后。用来说明显式禁止或显式允许特定机器人使用哪些URL路径。

Disallow和Allow前缀
  • Disallow和Allow规则要求大小写相关的前缀匹配。
  • 在进行比较之前,要将规则路径或URL路径中所有“被转义”的字符(%XX)都反转为字节(除了正斜杠%2F之外,它必须严格匹配)。
  • 如果规则路径为空字符串,就与所有内容都匹配。

接下来,书中给出了一段用Perl代码写的拒绝机器人访问的例子。例子太长了,这里就不列出了。

机器人排斥标签是以如下形式,通过HTML的META标签来实现的:

\<META NAME="ROBOTS" CONTENT=directvie-list\>

对于META标签指令,书中进行了总结(Page.250)。

  • INDEX
    告诉机器人它可以对页面的内容进行索引。

  • FOLLOW
    告诉机器人它可以爬行页面上的任何外连链接。

  • NOARCHIVE
    告诉机器人不应该缓存这个页面的本地副本。

  • ALL
    等价于INDEX、FOLLOW。

  • NONE
    等价于NOINDEX、NOFOLLOW。

对于机器人的规范,书中做了一些列的罗列。内容主要是一些操作以及对应的描述。

得到最广泛使用的Web机器人都是因特网搜索引擎。现在Web上很多最流行的站点都是搜索引擎。

本章基本上就这些,感觉看完本章道理上都明白了,但是没有什么感觉,我想可能需要做一些实践性或许体会更深刻吧。

第十章:HTTP-NG

本章讲的是下一代HTTP,即下一代系统(HTTP-NG)。

对于下一代系统,可以用三个英语单词来描述:“模块化及功能增强”(modularize and enhance)。HTTP-NG工作组建议讲协议模块化为三层(Page.263~Page.264)。

  • 第一层:报文传输层(message transport layer),这一层不考虑报文的功能,而是致力于端点间报文的不透明传输。
  • 第二层:远程调用层(remote invocation layer),定义了请求/响应的功能,客户可以通过这些功能调用对服务器资源的操作。
  • 第三层:Web应用层(Web application layer),提供了大部分的内容管理逻辑。
    HTTP-NG的很多基本原理和功能目标都是从CORBA和DCOM这样的结构化、面向对象的分布式对象系统中借鉴来的。

WebMUX

WebMUX是一个复杂的高性能报文系统,通过这个系统,可以在一个复用的TCP连接上并行地传输报文。可以对以不同速度产生的消耗的独立报文流进行高效的分组,并将其复用到一条或少数几条TCP连接上去。

Comments