据 NetCraft 公司统计,目前全球至少有 16 亿个网站、2 亿多个独立域名,而这个庞大网络世界的底层运转机制就是 HTTPHyperText Transfer Protocol。)。

起源

1989 年,任职于欧洲核子研究中心(CERN)的蒂姆·伯纳斯 - 李(Tim Berners-Lee)发表了一篇论文,提出了在互联网上构建超链接文档系统的构想。这篇论文中他确立了三项关键技术。

  • URI:即统一资源标识符,作为互联网上资源的唯一身份;
  • HTML:即超文本标记语言,描述超文本文档;
  • HTTP:即超文本传输协议,用来传输超文本。

这三项技术在如今的我们看来已经是稀松平常,但在当时却是了不得的大发明。基于它们,就可以把超文本系统完美地运行在互联网上,让各地的人们能够自由地共享信息,蒂姆把这个系统称为“万维网”(World Wide Web),也就是我们现在所熟知的 Web。所以在这一年,我们的英雄“HTTP”诞生了,从此开始了它伟大的征途。

HTTP/0.9

20 世纪 90 年代初期的互联网世界非常简陋,计算机处理能力低,存储容量小,网速很慢,还是一片“信息荒漠”。网络上绝大多数的资源都是纯文本,很多通信协议也都使用纯文本,所以 HTTP 的设计也不可避免地受到了时代的限制。这一时期的 HTTP 被定义为 0.9 版,结构比较简单,为了便于服务器和客户端处理,它也采用了纯文本格式。蒂姆·伯纳斯 - 李最初设想的系统里的文档都是只读的,所以只允许用“GET”动作从服务器上获取 HTML 文档,并且在响应请求之后立即关闭连接,功能非常有限。

HTTP/1.0

经过一系列的草案,HTTP/1.0 版本在 1996 年正式发布。它在多方面增强了 0.9 版,形式上已经和我们现在的 HTTP 差别不大了,例如:

  • 增加了 HEAD、POST 等新方法;
  • 增加了响应状态码,标记可能的错误原因;
  • 引入了协议版本号概念;
  • 引入了 HTTP Header(头部)的概念,让 HTTP 处理请求和响应更加灵活;
  • 传输的数据不再仅限于文本。

但 HTTP/1.0 并不是一个“标准”,只是记录已有实践和模式的一份参考文档,不具有实际的约束力,相当于一个“备忘录”。所以 HTTP/1.0 的发布对于当时正在蓬勃发展的互联网来说并没有太大的实际意义,各方势力仍然按照自己的意图继续在市场上奋力拼杀。

HTTP/1.1

1995 年,网景的 Netscape Navigator 和微软的 Internet Explorer 开始了著名的“浏览器大战”,再一次极大地推动了 Web 的发展,HTTP/1.0 也在这个过程中经受了实践检验。于是在“浏览器大战”结束之后的 1999 年,HTTP/1.1 发布了 RFC 文档,编号为 2616,正式确立了延续十余年的传奇。

从版本号我们就可以看到,HTTP/1.1 是对 HTTP/1.0 的小幅度修正。但一个重要的区别是:它是一个“正式的标准”,而不是一份可有可无的“参考文档”。这意味着今后互联网上所有的浏览器、服务器、网关、代理等等,只要用到 HTTP 协议,就必须严格遵守这个标准,相当于是互联网世界的一个“立法”。

HTTP/1.1 主要的变更点有:

  • 增加了 PUT、DELETE 等新的方法;
  • 增加了缓存管理和控制;
  • 明确了连接管理,允许持久连接;
  • 允许响应数据分块(chunked),利于传输大文件;
  • 强制要求 Host 头,让互联网主机托管成为可能。

Google 在 2015 年发布了 HTTP/2,RFC 编号 7540。

HTTP/2

HTTP/2 的制定充分考虑了现今互联网的现状:宽带、移动、不安全,在高度兼容 HTTP/1.1 的同时在性能改善方面做了很大努力,主要的特点有:

  • 二进制协议,不再是纯文本;
  • 可发起多个请求,废弃了 1.1 里的管道;
  • 使用专用算法压缩头部,减少数据传输量;
  • 允许服务器主动向客户端推送数据;增强了安全性,“事实上”要求加密通信。

虽然 HTTP/2 到今天已经四岁,也衍生出了 gRPC 等新协议,但由于 HTTP/1.1 实在是太过经典和强势,目前它的普及率还比较低,大多数网站使用的仍然还是 20 年前的 HTTP/1.1。

HTTP3

在 2018 年,互联网标准化组织 IETF 提议将“HTTP over QUIC”更名为“HTTP/3”并获得批准,HTTP/3 正式进入了标准化制订阶段,也许两三年后就会正式发布,到时候我们很可能会跳过 HTTP/2 直接进入 HTTP/3。

小结

回顾了 HTTP 协议的整个发展过程,在这里简单小结一下内容:

HTTP的发展:

  1. HTTP 协议始于三十年前蒂姆·伯纳斯 - 李的一篇论文;
  2. HTTP/0.9 是个简单的文本协议,只能获取文本资源;
  3. HTTP/1.0 确立了大部分现在使用的技术,但它不是正式标准;
  4. HTTP/1.1 是目前互联网上使用最广泛的协议,功能也非常完善;
  5. HTTP/2 基于 Google 的 SPDY 协议,注重性能改善,但还未普及;
  6. HTTP/3 基于 Google 的 QUIC 协议,是将来的发展方向。

HTTP不同版本特点:

  1. HTTP/0.9: 版本功能单一简单, 因前期设计简单, 后期版本更新就会比较容易
  2. HTTP/1.0: 功能相对0.9 更加丰富, 但并不是统一标准 只是一份文档, 不具约束力
  3. HTTP/1.1 : 相对1.0 添加了小规模更新, 但是它算是一份http统一的标准, 所有的http请求都需严格按照这个标准
  4. HTTP/2 : 相对1.1 提升了http请求的性能和安全性

推动 HTTP 发展的原动力?

  1. 用户需求。
  2. 人类好奇心。
  3. 逐利。

怎么理解 HTTP(超文本传输协议)?

​ 超文本传输协议=超文本+传输+协议,协议即约定,HTTP的本质是 P(Protocol),即一个协议,就是约定超文本怎么传输的,定义了服务端与客户端数据交互的标准。。

​ 初心就是分享信息,所以,简单、开放、有求有应,只针对文本,后来出现了音频、视频、动画、图片、超链接这些玩意,比纯文本复杂了一些,不过初心不改,所以,原则未变,只是需要调整一下适应这些正当其时的需求而已。

HTTP概念总览

HTTP是与不是什么?

HTTP 就是超文本传输协议,也就是 HyperText Transfer Protocol。

  • 其本质是协议。HTTP 是一个用在计算机世界里的协议。它使用计算机能够理解的语言确立了一种计算机之间交流通信的规范,以及相关的各种控制和错误处理方式。
  • 其次是一个“传输协议”。HTTP 是一个在计算机世界里专门用来在两点之间传输数据的约定和规范。
  • 对于“超文本”,我们最熟悉的就应该是 HTML 了,它本身只是纯文字文件,但内部用很多标签定义了对图片、音频、视频等的链接,再经过浏览器的解释,呈现在我们面前的就是一个含有多种视听信息的页面。

答:**“HTTP 是一个在计算机世界里专门在两点之间传输文字、图片、音频、视频等超文本数据的约定和规范”**

HTTP不存在单独实体、不是互联网,不是编程语言,不是HTML,不是孤立的协议

在互联网世界里,HTTP 通常跑在 TCP/IP 协议栈之上,依靠 IP 协议实现寻址和路由、TCP 协议实现可靠数据传输、DNS 协议实现域名查找、SSL/TLS 协议实现安全通信。此外,还有一些协议依赖于 HTTP,例如 WebSocket、HTTPDNS 等。这些协议相互交织,构成了一个协议网,而 HTTP 则处于中心地位。

总结:

  1. HTTP 是一个用在计算机世界里的协议,它确立了一种计算机之间交流通信的规范,以及相关的各种控制和错误处理方式。
  2. HTTP 专门用来在两点之间传输数据,不能用于广播、寻址或路由。
  3. HTTP 传输的是文字、图片、音频、视频等超文本数据。
  4. HTTP 是构建互联网的重要基础技术,它没有实体,依赖许多其他的技术来实现,但同时许多技术也都依赖于它。
HTTP相关概念
  1. 互联网上绝大部分资源都使用 HTTP 协议传输;

  2. 浏览器是 HTTP 协议里的请求方,即 User Agent;

  3. 服务器是 HTTP 协议里的应答方,常用的有 Apache 和 Nginx;

  4. CDN 位于浏览器和服务器之间,主要起到缓存加速的作用;

  5. 爬虫是另一类 User Agent,是自动访问网络资源的程序。

  6. TCP/IP 是网络世界最常用的协议,HTTP 通常运行在 TCP/IP 提供的可靠传输基础上;

    TCP/IP 协议是目前网络世界“事实上”的标准通信协议。

    在TCP/IP 协议实际上是一系列网络通信协议的统称,其中最核心的两个协议是 TCP(“Transmission Control Protocol”) 和 IP(“Internet Protocol”),其他的还有 UDP、ICMP、ARP 等等,共同构成了一个复杂但有层次的协议栈。在文章《TCP/IP与OSI网络分层模型》会详细介绍。

    HTTP 是一个”传输协议”,但它不关心寻址、路由、数据完整性等传输细节,而要求这些工作都由下层来处理。因为互联网上最流行的是 TCP/IP 协议,而它刚好满足 HTTP 的要求,所以互联网上的 HTTP 协议就运行在了 TCP/IP 上,HTTP 也就可以更准确地称为“HTTP over TCP/IP”。

  7. DNS 域名(“域名系统”,Domain Name System)是 IP 地址的等价替代,需要用域名解析实现到 IP 地址的映射;

  8. URI (统一资源标识符,Uniform Resource Identifier) 是用来标记互联网上资源的一个名字,由“协议名 + 主机名 + 路径”构成,俗称 URL( 统一资源定位符,Uniform Resource Locator);

    一个标准URI如下:

    http://nginx.org/en/download.html

    可以看到,URI 主要有三个基本的部分构成:

    • 协议名:即访问该资源应当使用的协议,在这里是“http”;
    • 主机名:即互联网上主机的标记,可以是域名或 IP 地址,在这里是“nginx.org”;
    • 路径:即资源在主机上的位置,使用“/”分隔多级目录,在这里是“/en/download.html”。
  9. HTTPS (HTTP over SSL/TLS”,)相当于“HTTP+SSL/TLS+TCP/IP”,为 HTTP 套了一个安全的外壳;

  10. 代理是 HTTP 传输过程中的“中转站”,可以实现缓存加速、负载均衡等功能。

HTTP请求与响应

下面两张图,是HTTP的报文结构体与真实HTTP图。

可以看到,HTTP 的报文结构,它是由 header+body 构成,请求头里有请求方法和请求目标,响应头里有状态码和原因短语。

HTTP请求方法

这里谈谈请求头里的请求方法。

HTTP/1.1 规定了八种方法,单词都必须是大写的形式。八种方法分别为:

  1. GET:获取资源,可以理解为读取或者下载数据;
  2. POST:向资源提交数据,相当于写入或上传数据;
  3. HEAD:获取资源的元信息;
  4. PUT:类似 POST;
  5. DELETE:删除资源;
  6. CONNECT:建立特殊的连接隧道;
  7. OPTIONS:列出可对资源实行的方法;
  8. TRACE:追踪请求 - 响应的传输路径。

其他方法都可以先放一放,最常见的还是GET和POST。

GET

它的含义是请求从服务器获取资源,这个资源既可以是静态的文本、页面、图片、视频,也可以是由 PHP、Java 动态生成的页面或者其他格式的数据。

GET 方法虽然基本动作比较简单,但搭配 URI 和其他头字段就能实现对资源更精细的操作。

PUT

GET 是从服务器获取数据,而 POST 方法则是相反操作,向 URI 指定的资源提交数据,数据就放在报文的 body 里。

安全

在 HTTP 协议里,所谓的“安全”是指请求方法不会“破坏”服务器上的资源,即不会对服务器上的资源造成实质的修改。

在 HTTP 协议里,所谓的“安全”是指请求方法不会“破坏”服务器上的资源,即不会对服务器上的资源造成实质的修改。

按照这个定义, GET 方法是“安全”的,因为它们是“只读”操作,只要服务器不故意曲解请求方法的处理方式,

无论 GET 操作多少次,服务器上的数据都是“安全的”。

而 POST 操作会修改服务器上的资源,增加或删除数据,所以是“不安全”的。

幂等

所谓的“幂等”实际上是一个数学用语,被借用到了 HTTP 协议里,意思是多次执行相同的操作,结果也都是相同的,即多次“幂”后结果“相等”。

很显然,GET既是安全的也是幂等的。(DELETE 可以多次删除同一个资源,效果都是“资源不存在”,所以也是幂等的。)

按照 RFC 里的语义,POST 是“新增或提交数据”,多次提交数据会创建多个资源,所以不是幂等的;(而 PUT 是“替换或更新数据”,多次更新一个资源,资源还是会第一次更新的状态,所以是幂等的。)(可以对比一下 SQL 来加深理解:把 POST 理解成 INSERT,把 PUT 理解成 UPDATE,这样就很清楚了。多次 INSERT 会添加多条记录,而多次 UPDATE 只操作一条记录,而且效果相同。)

HTTP状态响应码

服务器收到请求报文,解析后需要进行处理,具体的业务逻辑多种多样,但最后必定是拼出一个响应报文发回客户端。

响应报文 = 响应头 + 响应体数据

响应头 = 状态行 + 头字段。

接下来就谈谈状态行里的状态响应码。

RFC 标准把状态码分成了五类,用数字的第一位表示分类,范围在100~599。这五类的具体含义是:

  • 1××:提示信息,表示目前是协议处理的中间状态,还需要后续的操作;属于提示信息,是协议处理的中间状态,实际能够用到的时候很少。

  • 2××:成功,报文已经收到并被正确处理;

  • 3××:重定向,资源位置发生变动,需要客户端重新发送请求;301、302 和 304 分别涉及了 HTTP 协议里重要的“重定向跳转”和“缓存控制”,后面细说。

  • 4××:客户端错误,请求报文有误,服务器无法处理;

  • 5××:服务器错误,服务器在处理请求时内部发生了错误。

HTTP特点

首先奠定一下HTTP协议的五大特点,这里的讨论范围仅限于 HTTP/1.1

  • 灵活可扩展
  • 可靠传输
  • 应用层协议
  • 请求-应答通信模式
  • 无状态

接下来,谈谈这个五个特点带来的便利与缺点?

灵活可扩展

从HTTP的前世今生可以看出,HTTP最开始是比较简单的,慢慢的随着互联网的发展成长了起来。

在这个过程中,HTTP 协议逐渐增加了请求方法、版本号、状态码、头字段等特性。

而 body 也不再限于文本形式的 TXT 或 HTML,而是能够传输图片、音频视频等任意数据,这些都是源于它的“灵活可扩展”的特点。

可靠传输

第二个特点, HTTP 协议是一个“可靠”的传输协议。

这个特点显而易见,因为 HTTP 协议是基于 TCP/IP 的,而 TCP 本身是一个“可靠”的传输协议,所以 HTTP 自然也就继承了这个特性,能够在请求方和应答方之间“可靠”地传输数据。

它的具体做法与 TCP/UDP 差不多,都是对实际传输的数据(entity)做了一层包装,加上一个头,然后调用 Socket API,通过 TCP/IP 协议栈发送或者接收。

不过我们必须正确地理解“可靠”的含义,HTTP 并不能 100% 保证数据一定能够发送到另一端,在网络繁忙、连接质量差等恶劣的环境下,也有可能收发失败。

“可靠”只是向使用者提供了一个“承诺”,会在下层用多种手段“尽量”保证数据的完整送达。

当然,如果遇到光纤被意外挖断这样的极端情况,即使是神仙也不能发送成功。

所以,“可靠”传输是指在网络基本正常的情况下数据收发必定成功。

应用层协议

第三个特点,HTTP 协议是一个应用层的协议。

这个特点也是不言自明的,但却很重要。

HTTP 凭借着可携带任意头字段和实体数据的报文结构,以及连接控制、缓存代理等方便易用的特性,一出现就“技压群雄”,迅速成为了应用层里的“明星”协议。

只要不太苛求性能,HTTP 几乎可以传递一切东西,满足各种需求,称得上是一个“万能”的协议。

请求-应答通信模式

第四个特点,HTTP 协议使用的是请求 - 应答通信模式。

这个请求 - 应答模式是 HTTP 协议最根本的通信模型。

请求 - 应答模式也明确了 HTTP 协议里通信双方的定位,永远是请求方先发起连接和请求,是主动的,而应答方只有在收到请求后才能答复,是被动的,如果没有请求时不会有任何动作。

当然,请求方和应答方的角色也不是绝对的,在浏览器 - 服务器的场景里,通常服务器都是应答方,但如果将它用作代理连接后端服务器,那么它就可能同时扮演请求方和应答方的角色。

HTTP 的请求 - 应答模式也恰好契合了传统的 C/S(Client/Server)系统架构,请求方作为客户端、应答方作为服务器。

所以,随着互联网的发展就出现了 B/S(Browser/Server)架构,用轻量级的浏览器代替笨重的客户端应用,实现零维护的“瘦”客户端,而服务器则摈弃私有通信协议转而使用 HTTP 协议。

此外,请求 - 应答模式也完全符合 RPC(Remote Procedure Call)的工作模式,可以把 HTTP 请求处理封装成远程函数调用,导致了 WebService、RESTful 和 gRPC 等的出现。

无状态

“状态”其实就是客户端或者服务器里保存的一些数据或者标志,记录了通信过程中的一些变化信息。

TCP 协议是有状态的,一开始处于 CLOSED 状态,连接成功后是 ESTABLISHED 状态,断开连接后是 FIN-WAIT 状态,最后又是 CLOSED 状态。这些“状态”就需要 TCP 在内部用一些数据结构去维护,可以简单地想象成是个标志量,标记当前所处的状态,例如 0 是 CLOSED,2 是 ESTABLISHED 等等。

再来看 HTTP,那么对比一下 TCP 就看出来了,在整个协议里没有规定任何的“状态”,客户端和服务器永远是处在一种“无知”的状态。建立连接前两者互不知情,每次收发的报文也都是互相独立的,没有任何的联系。收发报文也不会对客户端或服务器产生任何影响,连接后也不会要求保存任何信息。

所以,HTTP 本质上是无状态的,每个请求都是互相独立、毫无关联的,协议不要求客户端或服务器记录请求相关的信息。

但不要忘了 HTTP 是“灵活可扩展”的,虽然标准里没有规定“状态”,但完全能够在协议的框架里给它“打个补丁”,增加这个特性。

HTTP优缺点

  1. HTTP 最大的优点是简单、灵活和易于扩展;
  2. HTTP 拥有成熟的软硬件环境,应用的非常广泛,是互联网的基础设施;
  3. HTTP 是无状态的,可以轻松实现集群化,扩展性能,但有时也需要用 Cookie 技术来实现“有状态”;
  4. HTTP 是明文传输,数据完全肉眼可见,能够方便地研究分析,但也容易被窃听;
  5. HTTP 是不安全的,无法验证通信双方的身份,也不能判断报文是否被篡改;
  6. HTTP 的性能不算差,但不完全适应现在的互联网,还有很大的提升空间。

无状态带来的好与坏。

  • 好处:

    因为服务器没有“记忆能力”,所以就不需要额外的资源来记录状态信息,不仅实现上会简单一些,而且还能减轻服务器的负担,能够把更多的 CPU 和内存用来对外提供服务。

    而且,“无状态”也表示服务器都是相同的,没有“状态”的差异,所以可以很容易地组成集群,让负载均衡把请求转发到任意一台服务器,不会因为状态不一致导致处理出错,使用“堆机器”的“笨办法”轻松实现高并发高可用。

  • 坏处:

    既然服务器没有“记忆能力”,它就无法支持需要连续多个步骤的“事务”操作。

    例如电商购物,首先要登录,然后添加购物车,再下单、结算、支付,这一系列操作都需要知道用户的身份才行,但“无状态”服务器是不知道这些请求是相互关联的,每次都得问一遍身份信息,不仅麻烦,而且还增加了不必要的数据传输量。

    所以,HTTP 协议最好是既“无状态”又“有状态”,不过还真有“鱼和熊掌”两者兼得这样的好事,这就是Cookie 技术

明文传输带来的好与坏

“明文”意思就是协议里的报文(准确地说是 header 部分)不使用二进制数据,而是用简单可阅读的文本形式。

  • 好处:

    不需要借助任何外部工具,用浏览器、Wireshark 或者 tcpdump 抓包后,直接用肉眼就可以很容易地查看或者修改,为我们的开发调试工作带来极大的便利。

  • 坏处:

    HTTP 报文的所有信息都会暴露在“光天化日之下”,在漫长的传输链路的每一个环节上都毫无隐私可言,不怀好意的人只要侵入了这个链路里的某个设备,简单地“旁路”一下流量,就可以实现对通信的窥视。

关于它的性能

  • HTTP 协议基于 TCP/IP,并且使用了“请求 - 应答”的通信模式,所以性能的关键就在这两点上。
  • TCP 的性能是不差的,但现在互联网的特点是移动和高并发,不能保证稳定的连接质量,所以在 TCP 层面上 HTTP 协议有时候就会表现的不够好。
  • 而“请求 - 应答”模式则加剧了 HTTP 的性能问题,这就是著名的“队头阻塞”(Head-of-line blocking),当顺序发送的请求序列中的一个请求因为某种原因被阻塞时,在后面排队的所有请求也一并被阻塞,会导致客户端迟迟收不到数据。
  • 为了解决这个问题,就诞生出了一个专门的研究课题“Web 性能优化”,HTTP 官方标准里就有“缓存”一章(RFC7234),非官方的“花招”就更多了,例如切图、数据内嵌与合并,域名分片、JavaScript“黑科技”等等。
  • 不过现在已经有了终极解决方案:HTTP/2 和 HTTP/3,后面会展开来讲。