HTTP权威指南

  1. HTTP Hypertext Transfer Protocol 超文本传输协议

  2. 阅读人群

  • 软硬件工程师:可以作为HTTP及相关Web技术参考书使用
  • 系统架构师和网络管理员:了解如何设计、实现并管理复杂的网络架构
  • 性能工程师和分析人员:从缓存和性能优化的相关章节获益
  • 市场营销和咨询专家:通过概念介绍更好的理解Web技术的前景

HTTP:Web基础

HTTP概述

1
2
客户端->服务器: http请求“请将名为/index.html的文档发给我”
服务器-->客户端: “好的,这就是。文档是以HTML格式给出的,有3150字节长”
  • 资源:所有类型的内容来源都是资源

  • 类型:所有HTTP对象数据都会附加一个MIME类型的数据格式标签,用它来描述并标记多媒体内容,浏览器根据MIME类型去知道应该如何处理这个对象。

    • MIME类型是一种文本标记,表示一种主要的对象类型和一个特定的子类型,中间由一条斜杠来分隔
  • URI:服务器资源名被称为统一资源标识符(Uniform Resource Identifier URI)

  • URI有两种形式:URL和URN

    • URL: 统一资源定位符,是资源标识符最常见的形式,描述一台特定服务器上某资源的特定位置
      • 第一部分http:// 被称为方案(scheme),告知web客户端怎么访问资源
      • 第二部分www.oreilly.com 指的是服务器的位置
      • 第三部分是资源路径
      • 几乎所有的URI都是URL
    • URN:统一资源名,是作为特定内容的唯一名称使用的,与目前的资源所在地无关。可以将资源四处搬移和用同一个名字通过多种网络访问协议访问资源
      • 因特网标准文档RFC 2141 用URN命名:urn:ietf:rfc:2141
      • URN仍然处于试验阶段
  • HTTP支持几种不同的请求命令,常见:

    • GET 从服务器向客户端发送命名资源
    • PUT 将来自客户端的数据存储到一个命名的服务器资源中去
    • DELETE 从服务器中删除命名资源
    • POST 将客户端数据发送到一个服务器网关应用程序
    • HEAD 仅发送命名资源响应中的HTTP首部
  • 状态码:一个三位数字的代码

  • HTTP报文

    • 请求报文(request message):从web客户端发往web服务器的HTTP报文
    • 响应报文(response message):从服务器发往客户端
    • HTTP报文包括三个部分:
      • 起始行
      • 首部字段,每个首部字段包含一个名字和一个值,用冒号分隔,首部以一个空行结束
      • 主体:可以包含任意二进制数据/文本
      • 每行都以一个由两个字符组成的行终止序列作为结束:回车符(ASCII码13)和换行符(ASCII码10),但稳健的应用程序也应该接受单个换行符作为行的终止
  • HTTP使用传输控制协议(Transmission Control Protocol,TCP)来传输报文数据

  • 在客户端向服务器发送报文之前,需要用网际协议(Internet Protocol,IP)地址和端口号建立一条TCP/IP连接

  • telnet可以直接与web服务器进行通讯,可以很好的模拟HTTP客户端 telnet www.joes-hardwarecom 80

  • HTTP协议版本

    • HTTP/0.9 1991原型版本,有很多严重设计缺陷,只支持GET,很快被HTTP/1.0取代
    • HTTP/1.0 第一个广泛使用的HTTP版本,集合了一系列的最佳实践
    • HTTP/1.0+ 非正式的HTTP扩展版本
    • HTTP/1.1 引入重要的性能优化措施,并删除一些不好的特性
    • HTTP/2.0 重点关注的是性能的大福优化以及更强大的服务逻辑远程执行框架
  • 代理:位于客户端和服务器之间,接收所有客户端的HTTP请求,并将这些请求转发给服务器(可能会对请求进行修改之后)

  • 缓存:web缓存(web cache)和代理缓存(proxy cache)是一种特殊的HTTP代理服务器,将代理传送的文档复制保存起来,客户端从附近的缓存下载文档

  • 网关:一种特殊的服务器,作为其他服务器的中间实体使用。通常用于将HTTP流量转换成其他的协议

  • 隧道:两条连接之间对原始数据进行盲转发的HTTP应用程序,HTTP隧道常用在通过HTTP连接承载加密的安全套接字(SSL)流量

  • Agent代理:发起HTTP请求的客户端程序(如:web浏览器,网络蜘蛛)

URL与资源

组件 描述 默认值
scheme 使用哪种协议(大小写无关)
user 用户名 匿名
password 密码 E-mail地址
host 宿主主机名/ip地址
port 宿主服务器监听端口号 HTTP默认80
path 资源路径,通常像一个分机的文件系统路径
params 指定输入参数,与path使用分号分隔
query 查询的内容没有通用格式,与params用问号分隔
frag 一小片或一部分资源的名字,不会把frag发送给服务器,在客户端内部使用,通过字符#分隔
  • URL有两种方式:绝对的和相对的

  • 自动扩展URL:有些浏览器会对用户输入的URL进行自动扩展(主机名扩展和历史扩展)

  • URL字符集:通过转义序列,可以用US-ASCII字符集的有限子集对任意字符值或数据进行编码了,实现了可移植性和完整性

  • 转义表示法包含一个百分号%,后面跟着两个表示字符的ASCII码的十六进制数
    字符 | ASCII码

  • | -
    ~ | 126(0x7E)
    空格 | 32(0x20)
    % | 37(0x25)

  • URL中,有一些字符被保留起来,有着特殊的含义

HTTP报文

  • HTTP报文时HTTP应用程序之间发送的数据块,以一些文本形式的元信息(meta-information)开头,即简单的格式化数据块

  • 状态码分类
    整体范围 | 已定义范围 | 分类

  • | - | -
    100199 | 100101 | 信息提示
    200299 | 200206 | 成功
    300399 | 300305 | 重定向
    400499 | 400415 | 客户端错误
    500599 | 500505 | 服务端错误

  • 首部分类:通用首部,请求首部,响应首部,实体首部,扩展首部

  • 首部延续行:将长的首部行分为多行可以提高可读性,多出来的每行前面至少要有一个空格/制表符TAB

  • 安全方法:GET和HEAD方法都被认为是安全的

连接管理

  • TCP为HTTP提供了一条可靠的比特传输管道

  • TCP的数据时通过名为IP分组(IP数据报)的小数据块来发送的

  • 每个TCP段都是有IP分组承载,从一个IP地址发送到另一个IP地址

  • 每个IP分组中都包括:

    • 一个IP分组首部(通常为20字节)(包含了源和目的IP地址,长度和其他一些标记)
    • 一个TCP段首部(通常为20字节)(包含TCP端口号,控制标记,以及用于数据排序和完整性检查的一些数字值)
    • 一个TCP数据块(0个或者多个字节)
  • TCP API隐藏了所有底层网络协议的握手细节,以及TCP数据流和IP分组之间的分段和重装细节

  • HTTP事务的时延: DNS查询->连接->请求->处理->响应->关闭

    • 根据URI确认服务器IP和端口,若当前系统DNS缓存没有该解析数据,需要通过DNS解析域名
    • 客户端和服务器之间建立一条TCP连接,有连接建立时延
    • 客户端传输请求报文,服务器处理请求报文都需要时间
    • 服务器回复HTTP响应,也需要时间
  • 最常见的TCP相关时延:

    1. TCP连接建立握手,如果连接只是用来传送少量数据,这些交换过程就会严重降低HTTP的性能(小的HTTP事务可能会在TCP建立上花费50%的时间)

      • 每个TCP段都有一个序列号和数据完整性校验和,每个段的接受者收到完好的段时,都会向发送者回送小的确认分组。如果发送者没有在指定的窗口时间内收到确认信息,发送者就认为分组已被破坏和损毁,并重发数据。
    2. 用于捎带确认的TCP延迟确认算法

      • 延迟确认算法会在一个特定的窗口时间(通常是100~200毫秒)内将删除确认存放在缓冲区中,以寻找捎带它的输出数据分组,如果在那个时间段内没有输出数据分组,就将确认消息放在单独的分组中传送
      • HTTP具有双峰特征的请求-应答行为降低降低了捎带信息的可能性,通常,延迟确认算法会引入相当大的时延,可以根据使用的操作系统的不同,可以调整或禁止延迟确认算法
    3. TCP慢启动拥塞控制

      • TCP数据传输的性能还取决于TCP连接的使用期。TCP连接会随着时间进行自我“调谐”,起初会限制连接的最大速度,如果数据成功传输,会随着时间的推移提高传输的速度,这种调谐被称为 TCP慢启动,用于防止因特网的突然过载和拥塞
      • 新连接会比已经交换过一定量数据的连接慢一些,所以HTTP中有一些可以重用现存连接的工具
    4. 数据聚集的Nagle算法

      • TCP有一个数据流接口,应用程序可以通过它将任意大小的数据放入TCP栈中,但是每个TCP段中至少装载40个字节的标记和首部,如果TCP发送大量包含少数数据的分组,网络的性能就会严重下降
      • Nagle算法试图在发送一个分组之前,将大量TCP数据绑定在一起,以提高网络效率。只有当所有的其他分组都被确认之后,Nagle算法才允许发送非全尺寸的分组。只有当挂起分组被确认,或者缓存中累积了足够发送一个全尺寸分组的数据时,才会将缓存的数据发送出去
      • 会引发几种HTTP性能问题
        • 小报文无法填满一个分组,因为等待那些永远不会到来的额外数据而产生时延。
        • Nagle算法会阻止数据的发送,知道有确认分组抵达为止,但确认分组自身会被延迟算法延迟100~200毫秒
      • 栈中设计参数TCP_NODELAY,禁用Nagle算法,但要确认会向TCP写入大块的数据
    5. TIME_WAIT时延和端口耗尽

      • TIME_WAIT端口耗尽是很严重的性能问题,会影响性能基准,但现实上相对较少出现
      • 当TCP端点关闭TCP连接时,会在内存中维护一个小的控制块,用来记录最近所关闭连接的IP地址和端口,这类信息会被维护一段时间(2MSL,通常为2分钟),以确保在这段时间不会创建具有相同地址和端口号的新连接。
      • 高速路由器的使用,使用重复分组几乎不可能在连接关闭的几分钟之后出现在服务器上。一般会将2MSL设置为一个较小的值,但超过此值时,分组确实会被复制,如果来自之前连接的复制分组插入了具有相同连接值的新TCP流,会破坏TCP数据
      • 但性能基准测试时,客户端IP地址数有限,并且服务器通常对80端口监听,用TIME_WAIT防止端口号重用时,这些情况也限制了可用的连接值组合: 客户端每次连接需要获取一个新的端口号,以实现连接的唯一性,但可用源端口数量有限(如:6W个),而在2MSL(120秒)内连接无法重用,连接率就被限制在了60000/120=500次/秒,可以增加客户端负载机器数量或者使用几个虚拟IP地址增加更多的连接组合,还有就是减少2MSL的时间
  • Connection首部可以承载3中不同类型的标签

    • HTTP首部字段名,包含了一些连接有关的信息,不能将其转发出去
    • 任意标签值,用于描述此连接的非标准选项
    • 值close,说明操作完成之后需关闭这条持久连接
  • 串行事务处理时延:如果只对连接进行简单的管理,TCP的性能时延可能会叠加起来

    • 串行加载引入实际时延之外,还让人觉得加载速度很慢,用户希望同时加载多幅图片
    • 浏览器在加载完毕之前无法获取对象尺寸,在加载到足够多的对象之前,无法在屏幕上显示任何内容。
  • 提高HTTP的连接性能:

    1. 并行连接

      • 并行连接并不一定总是更快,在网络带宽不足时,并行加载对象会竞争有限的带宽
      • 大量连接会消耗更多的内存资源,从而引发自身的性能问题:100个客户,每个客户打开100个连接,服务器就要负责处理10000个连接,这会造成服务器性能的严重下降。
      • 实际上浏览器会把并行连接总数限制为一个较少的值(通常为4个),服务器可以随意关闭来自特定客户端的超量连接
      • 可能让人感觉更快一些,多个组件对象同时出现在屏幕上,用户能够看到加载的进展,会认为web页面加载得更快一些
    2. 持久连接:在事务处理结束之后保持在打开状态的TCP连接被称为持久连接。可以避开缓慢的连接建立阶段和避免慢启动的拥塞适用阶段。

      • 持久+并行连接
      • HTTP/1.0+keep-alive连接
      • HTTP/1.1 presistent连接(持久连接在默认情况下是激活的,关闭连接需要显式添加Connection: close,但客户端和服务器仍然可以随时关闭空闲的连接)
      • keep-alive操作:Connection: Keep-Alive
      • keep-alive选项:Keep-Alive: max=5, timeout=100
      • keep-alive无法与不支持Connection首部的代理进行互操作(Connection首部是个逐跳首部,只适用于跳跳传输链路,不应该沿着传输链路向下传输)
      • 每个持久连接都只适用于一跳传输
      • HTTP/1.1的代理服务器不应该与HTTP/1.0客户端建立持久连接
      • 一个用户客户端对任何服务器或代理最多只能维护两条持久连接,以防止服务器过载
    3. 管道化连接

      • HTTP/1.1允许在持久连接上可选地使用请求管道。在响应到达之前,可以将多条请求放入队列。当第一条请求通过网络流向另一端的服务器时,第二条和第三条请求也可以开始发送。在高时延的网络条件下,这样做可以降低网络的环回时间,提高性能
      • 客户端不应该以管道化方式传送非幂等请求(比如POST)
    4. 复用的连接

  • 关闭连接的奥秘

    • 所有的HTTP客户端、服务器或代理都可以在任意时刻关闭一条TCP传输连接
    • 每条HTTP响应都应该有精确的content-lenght首部,用以描述响应主体的尺寸,当实体长度不匹配,接收端就应该质疑长度的正确性(但缓存代理不应该缓存这条响应,而是原封不动的转发出去)
    • HTTP应用程序要做好正确处理非预期关闭的准备
    • 关闭连接的输出信道总是很安全的
    • 关闭连接的输入信道比较危险,除非知道另一端不打算再发送其他数据了。如果向已关闭的输入信道发送数据,操作系统就会向另一端的机器回送一条TCP“连接被对端重置”的报文(该重置信息会清空对端输入缓冲区,已缓存的未读响应数据都丢失了)
    • 正常关闭的应用程序首先应该关闭它们的输出信息到,然后等待连接另一端的对等实体关闭它的输出信道(可以周期性检查其输入信道的状态),当两端都告诉对方它们不会再发送任何数据之后,连接就会被完全关闭,而不会有重置的危险(可以在一定时间区间内对端没有关闭输入信道,应用程序可以强制关闭连接,以节省资源)。

HTTP结构

Web服务器

代理

缓存

集成点:网关、隧道及中继

Web机器人

HTTP-NG


识别、认证与安全

客户端识别与cookie机制

基本认证机制

摘要认证

安全HTTP


实体、编码和国际化

实体和编码

国际化

内容协商与转码


内容分发与发布

Web主机托管

发布系统

重定向与负载均衡

日志记录和使用情况跟踪

坚持原创技术分享,您的支持将鼓励我继续创作!.