HTTP(Hyper Text Transform Protocol)是指超文本传输协议,主要用于Web之间的通讯协议。

HTTP协议访问资源需要一个访问地址,称之为统一资源标识符(URI)

  • URI:Uniform Resource Identifier
    其中URI有两种定位方式:使用地址进行定位(URL),或者使用名称进行定位(URN),其中URN将会是未来的资源访问方式,但仍然处于探索阶段。

  • URL: Uniform Resource Location

一个URL应包含:方案://用户名:密码@主机:端口/路径;参数=参数值?查询键=查询值#片段
一个简单的示例: http://ourdark:password@www.ourdark.org:443/path/index.htm;para=test?id=1#top

其中用户名和密码,以及默认的端口可以省略(http的80端口,和https的443端口),方案可以是http、https、ftp等可用方案。路径可以包含较长的path和资源名称,其中片段跟在#之后,用于访问http文档的片段内容,但服务器并不会收到和处理片段信息,仅在客户端处理

  • URN:Unitform Resource Name
    一个例子:访问RFC 2141文档的URN为urn:ieft:rfc:2141

一个HTTP事务包含一个客户端的请求以及服务器端的响应,不论是流入还是流出均包含以下部分:

  • 初始行
  • 首部
  • 报文

初始行给出了一个请求资源的位置(HTTP URL的Schema),以及请求的方法(Get、POST、HEAD、OPTION、PUT、DELETE、etc.)

首部给出了一个可扩展的键值对,例如:Content-Type: text/plaint

报文(主体)给出了请求/响应的的明文数据内容

一个HTTP事务流程,客户端获取URL之后,将域名解析为IP地址(DNS),如果不包含端口号,则使用方案的默认端口号,经过一系列的解析和验证,生成请求流报文。请求流包括请求的方法,协议版本号(HTTP/1.1)以及请求的资源路径组成初始行,首部包含了请求的可用的首部(header)例如:Content-Type:text/plaint,报文是一个箱子,里面包含实体(数据),数据也是实体的主体,主体在不同的情况下可以为空。服务器在接到客户端的请求后响应对应的初始行、首部和报文,以及首部中的状态码。

首部:通用首部、请求首部、响应首部、实体首部以及扩展首部。
状态码:10x continue、20x成功、30x重定向、40x错误以及50x服务器错误。

值得注意的是,请求行的方法中GET和HEAD被设计为一个等幂操作。

事实上,HTTP协议并不是一个底层协议,其连接底层主要靠TCP协议来实现。网络层的结构为从上到下为:

HTTP(应用层)
TSL/SSL(安全层)
TCP(传输层)
IP(网络层)
网络接口(数据链路层)

HTTP协议是一个无状态的协议,其下层基于TCP协议在每次事务中完成连接、传输和连接关闭。

TCP套接字实现了TCP协议的主要接口:套接字创建、绑定端口号、连接、监听、等待数据、读取/写入字节、完全关闭连接,关闭流入或流出、获取/设置套接字选项。

一个TCP连接需要三次握手,亦即客户端向服务器发送一个小的TCP分组,设置SYN。如果服务器接收则相应SYN并ACK,客户端收到服务器SYN和ACK后向服务器发送ACK信息。

HTTP的性能很大程度上依赖于TCP的设计原理,尤其是HTTP请求实体较小而频繁的情况,其中考虑:

  • HTTP事务延迟: DNS解析、连接事务数量、服务器处理、响应。取决因素在于硬件速度、网络速度、服务器负载、报文大小,服务器和客户端的距离(电子光速也需要花费时间)
  • TCP连接握手延迟:握手可能占小事务时间花费的50%
  • 延迟确认:由于TCP是一个安全协议,不同于UDP,服务器会在接收到数据后稍带一个确认信息,这个算法(按照时间窗口进行稍带等待/确认等待)会影响性能
  • TCP慢启动:TCP为了防止internet突然阻塞,会采用2的n次幂进行缓慢提速,被称之调谐也会影响HTTP传输性能。
  • Nagle算法/TCP_NODELAY:该算法提供了数据统一处理的VP机制,他与NO_DELAY受到实际情况的挑战
  • TIME_WAIT端口耗尽:TCP为了防止端口重复维护并禁用了2MSL时间窗口内的端口,60000个端口在高并发的情况下,可能会导致端口耗尽。

另外HTTP的处理机制也可能引发性能问题:

  • 串行处理延迟
  • 并行连接局限性(客户端网络状况、服务器处理能力、代理处理能力)
  • 持久连接(不可预期的关闭,服务器永远不知道关闭时客户端是不是刚好发来了请求、空闲连接、Keepalive盲中继的哑代理),代理有时候会为我们提供很多的便利(过滤、访问控制、安全防火墙、缓存[CDN]、反向代理、解码器、负载均衡[DNS轮询]、流量监控),在使用代理的情况下,一定要了解代理的穿透能力和支持能力。
  • 管道化连接(请求队列缓存)

一个服务器的任务是:

  • 接受连接
  • 接收请求
  • 处理请求
  • 访问其资源
  • 构建响应
  • 发送响应
  • 服务器事务日志

很多情况下,服务器可能面临几个问题:带宽瓶颈、瞬间拥塞和距离延迟。当服务器处理大量频繁的客户端请求时,会引起宽带流量,遇到特定的时间节点客户端同时发起请求将会触发网络高峰引起瞬间的网络拥塞,以及超远距离传输引起网络延迟。

缓存在这一过程中,定性的提供了缓解服务器压力的处理方式。缓存包含命中、未命中和再验证的情况,当客户端请求命中缓存时将根据缓存策略进行加载或再验证。对于命中的缓存的指标包括命中率,局部命中的字节命中率,为了更高效的缓存利用,大尺寸的缓存命中将使用字节命中来进行缓存的验证和缓存新鲜度更新。对于网络结构中,还存在私有缓存(浏览器缓存)和共享缓存(服务器代理),整体网络结构:

  • 一级缓存命中
  • 地区性网络
  • 二级缓存
  • 广域网
  • 原始服务器

缓存处理的步骤:

  • 接收报文请求
  • 解析报文中的初始行、首部和主体
  • 查询可用副本
  • 新鲜度检查
  • 创建响应
  • 发送响应
  • 日志记录

缓存的控制能力按照优先级递减:no-store(禁止对响应进行复制)、nocache(缓存副本,但再验证前不能提供使用)、must-revalidate(必须进行再验证)、max-age(新鲜期)、expires(绝对过期时间)。试探性过期验证则使用LM-Factor算法,频繁更新的文档被更新的概率远远大于很久没有更新的文档。注意,虽然HTTP协议提供了缓存命中统计,但由于客户端可以随意清除缓存,广告监测将无法完全信任客户端缓存。

在整个HTTP应用中,网关、代理、中继和隧道是重要的组成部分。网关进行协议的转换,中继进行盲转发,代理则是中继的加强。隧道则可以让客户端使用非HTTP协议传输非HTTP流量。

在网络爬虫应用中,应注意环路的出现。首先应对的是自身的逻辑问题,能够分析和解决路径中的环,理解URL的别名以及文件名环路。有时候难免的,一个不愿被搜索引擎注意的个人站点会创建虚拟的递归空间从而是爬虫机器人陷入僵局。为了有效的避免可以采取:规范URL、广度优先爬行、节流、限制URL大小、黑名单、模式监测内容指纹和人工监视。Web是一片荒野,机器人是拾荒者但终究会陷入任何都技术无能为力困境,机器人设计者必须考虑诊断和日志,避免愤怒的网民带来无理的抗争。快速响应问题将使原本开朗的空间管理员变得没有那么的愤怒。做为被访问者可以根据非正式的契约决定拾荒者可以访问哪些资源,在根目录下存储robots.txt对机器人进行授权和拦截,但这些都是自愿的。反之,任何一方都可能面临一个愤怒的对手。

识别和认证
安全HTTP(SSL)和数字证书
编码和国际化(需要服务器自动识别结合客户端协商)
重定向和负载均衡
日志与跟踪

附录:

  • URI方案
  • HTTP状态码
  • HTTP首部参考
  • MIME类型
  • BASE-64编码
  • 摘要认证
  • 语言标记
  • MIME字符集注册表