这篇文章包括对 REST 架构、HTTP 协议本身的介绍, HTTP 的应用, 分布式系统组成成分介绍, TCP/IP 协议族的介绍以及穿插在各个知识点的扩展.

读之前请注意:

这篇文章是我在读完 David Gourley 等人所著的《HTTP权威指南》后写的读书笔记, 文章内容包括我从这本书和网上学到的知识. 其中很大概率会有错误、片面、过时的内容, 仅供参考. 建议读者自己去读这本书或者直接阅读RFC 中 HTTP 相关标准.

正文

HTTP 概述

1989年3月12日, Tim Berners-Lee 发表了一篇论文《Information Management: A Proposal》, 提出一个基于互联网的超文本系统, 可以让信息在 CERN 各种设备上的显示、查找、共享更加方便, world wide web也被首次提及. 1990年10月前, Tim Berners-Lee 相继定义了三种 web 基础技术的初始版本: 命名方案(URI)、通信协议(HTTP)和表示信息的超文本标记语言HTML, 并写出了世界上第一个浏览器和web站点. 后来, 这三种基础技术经W3C(Tim Berners-Lee 创建) 和 IETF 组织标准化, 发布了一系列RFC, HTTP 版本也从 HTTP 0.9 到现在的 HTTP 2.

如今, HTTP 广泛用于客户端和服务器端之间多媒体信息的传输, 是一种应用层协议, 基于TCP/IP 协议族. 简化过程为:

  1. 客户端发起一个HTTP请求, 内容为 HTTP 请求报文, 报文分为首部和主体, 首部会使用统一标识符 URL 表明想要的资源, 使用方法来表明动作, 使用首部来表明报文的各种配置信息等; 主体是要发送的数据;
  2. 服务端接收到请求后会解析, 查找到资源后使用HTTP报文返回, 报文也包括了首部和主体, 分别用于指定响应的配置信息和具体的资源. 然后服务器关闭连接, 响应结束.

这个过程称作一个HTTP事务.

上面的过程只是简化版, 实际中, 从客户端到源服务器的请求可能会更加复杂——首先, 在发送HTTP请求之前, 客户端会先使用本地DNS缓存或者远程DNS服务器将URL解析为IP地址, 然后用IP地址和端口号和服务器建立TCP/IP连接, 有时还会进行SSL握手建立加密的连接后才会发送HTTP请求. 接着可能会经过各种代理、网关、隧道等, 有时甚至直接从CDN中的某个就近缓存服务器返回了请求, 没有到达源服务器. 而服务端接受到请求后, 除了接受请求并解析、返回本地资源外, 也可能会做监视连接、客户端认证、执行程序生成动态内容、重定向、记录日志等…

日益增长的需求和不断变化的应用, 使 HTTP 逐渐变得复杂起来, HTTP 标准的版本也因此不断演变. HTTP, 就像其他web技术一样, 先有需求和应用, 才有下一个标准. 实践总是走在理论标准前面.

代理位于客户端和源服务器之间, 在客户端和源服务器交流之前处理请求或响应, 用处很广泛, 将在下文讨论; 网关用于转换协议, 比如你发了一个HTTP请求一个需要用FTP协议请求的文件, HTTP/FTP网关就会转换协议; 隧道会在连接的两端之间建立一条通道, 在这条通道上用HTTP连接承载其他数据(如SSL流量), 经过代理时会直接转发, 这样的话就可以让客户端与服务器直接进行TLS(SSL)握手来建立HTTPS连接.

有一些细节需要讨论:

  • 为什么要创建一个新的协议而不是继续使用原来的协议?

    Tim Berners-Lee 在设计HTTP之初提到过, 为了更好地管理信息(基于HTML), 新有的协议要基于原有协议并且更有利于信息管理(能够传送HTML):

    Tim Berners-Lee 在1991年发表

  • 为什么HTTP是一个基于TCP/IP的应用层协议?

    TCP/IP是全世界的计算机和网络设备常用的基础协议集, 位于OSI协议栈的传输层隐藏了不同设备的特点和弱点, 提供可靠的通信, 基于TCP/IP, 无需担心底层影响, 保证了数据的稳定传输. 另一方面, 应用层协议方便应用程序发起连接而不需要关心底层实现.

URL与资源

web 及HTTP 诞生之前, 如果想要访问服务器上的某个文件, 你需要使用FTP协议连接到服务器再下载到本地浏览. 后来, 在万维网和HTTP诞生之际, 为了在不同环境、不同系统下(可移植)能够通用地、方便地访问服务器中的某个资源, Tim Berners-Lee 配套地定义了Universal Resource Identifier 统一资源标识符URI来唯一指定某个资源, 这样以来, 使用HTTP协议发送请求就可以方便的指定资源. URI 包括以地址为标识符的URL(Locators)方案和以名字为标识符的URN(Names)方案. 早期的

  • URL 通过描述资源的位置来标识资源, 但不会反映资源内容的变化, 且一旦某个资源被移动, 这个URL 也就失效了;
  • URN 通过资源的名称来标识资源, 与资源所处的位置无关, 因此就算资源被移动仍能找到(尚未实现).

URL 结构如下(图片来源):

协议、域名和端口指明了资源所在空间, 路径指明了具体位置, 问好及后面的query组成了查询组件, 可以服务端程序传递查询参数. URL 会将一些特殊字符转义以避开安全问题, 如空格会被转义成 “%20”, 汉字会转成 ASCII 码等.

URL 末尾还有一个片段组件, 以#开头, 用来表示某个文档中的某个部分. 值得一提的是, 改变片段值并不会触发页面刷新, 另外HTML5也定义了相关标准 API 来允许开发者操作片段, 因此常作为页面路由的基础实现.

这一切是怎么来的?

The Elephant in the room

HTTP 和 URL 有各种特性, 如客户端-服务端模式、无状态连接、缓存、统一接口等, 这些特性使得 HTTP和 URL 在如今日益复杂的分布式网络系统中出色的完成了工作, 但这里有一个深层的问题非常值得探讨: Why? 为什么会有这些特性(使得Web取得了巨大的成功)? 为什么要这样设计? 当然是有产生背景的…

1996年左右, HTTP/1.1专家组的负责人 Roy Fielding 和他的同事们在HTTP/1.1协议的设计工作中,对于Web之所以取得巨大成功,在技术架构方面的因素做了一番深入的总结。Fielding将这些总结纳入到了一套理论框架之中,然后使用这套理论框架中的指导原则,来指导HTTP/1.1协议的设计方向。

1999年6月, IETF 正式发布了 HTTP 1.1 (RFC 2626\RFC 2617). HTTP/1.1协议设计的极为成功,以至于发布之后整整10年时间里,都没有多少人认为有修订的必要。

Fielding在完成HTTP/1.1协议的设计工作之后第二年(2000年), 在他的博士学位论文《Architectural Styles and the Design of Network-based Software Architectures》中,Fielding更为系统、严谨地阐述了这套理论框架,并且使用这套理论框架推导出了一种新的架构风格,他为这种架构风格取了一个令人轻松愉快的名字“REST”——Representational State Transfer(表述性状态转移)的缩写。

​ ——《理解本真的REST架构风格》

REST — Web应用架构背后的设计思想

REST 是一种分布式系统软件架构风格, 是为运行在互联网环境的分布式超媒体系统量身定制的。REST 架构应用在了 URL 标准 和 HTTP 1.1 协议上, 它是所有Web应用都应该遵守的架构设计指导原则。

对于 Web 这样一个大型分布式超文本系统有几个主要需求: 客户-服务器模式、无状态、缓存、统一接口、分层系统等. 对于这几个需求, REST是这么设计的:

而使用 HTTP 1.1协议的Web系统架构通常如下:

左边是客户端, 中间是各种代理、缓存、网关等, 右边是服务端.

想必你已经明白了为什么 HTTP 1.1要这么设计, 为什么HTTP 1.1有这样那样的特性, 这是因为HTTP/1.1协议是一种REST架构风格的架构实例.

REST 不仅仅对 HTTP1.1协议的设计起到指导作用, 还对早先的 URL 设计提出了一些建议, 其中突出的是将URL语义化:

图片截图自《架构风格与基于网络的软件架构设计》中文版, 译者: 李琨

REST 5个核心概念:

  • 资源——服务器上的超媒体, 资源是一种映射
  • 资源的表述——资源的格式, HTML/JSON等
  • 状态转移——在客户端和服务器端之间转移(transfer)代表资源状态的表述
  • 统一接口——通过统一的接口来对资源执行各种操作, 对于每个资源执行HTTP定义的操作
  • 超文本驱动;

REST风格的架构所具有的6个的主要特征:

  • 面向资源(Resource Oriented)
  • 可寻址(Addressability)
  • 连通性(Connectedness)——避免设计孤立的资源,除了设计资源本身,还需要设计资源之间的关联关系,并且通过超链接将资源关联起来。
  • 无状态(Statelessness)
  • 统一接口(Uniform Interface)
  • 超文本驱动(Hypertext Driven)

REST 这些特性指引了 HTTP 1.1协议基于HTTP 1.0协议的扩展方向

具体请参考《理解本真的REST架构风格》

RESTful API——REST 风格的接口

RESTful API 就是具有 REST 风格的接口, 它体现了 REST 面向资源、URL 语义化、统一接口等几大特性:

  • 多端统一接口
  • 使用 HTTP 动词让请求有意义
  • 提供语义化的URL;
  • 使用 HTTP 响应码来展示状态
  • 最好提供 JSON和XML 两种格式, JSON 优先
  • 将资源细粒度化
  • 考虑连通性

具体实践请参考http://www.restapitutorial.com/或https://restfulapi.net/

HTTP 报文

HTTP 报文承载了HTTP请求的各种信息, 包括起始行、首部和实体

TCP 连接

web 服务器

代理、缓存、CDN、DNS

HTTP认证

HTTP 2

参考

https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol

https://en.wikipedia.org/wiki/URL

https://www.w3.org/Protocols/WhyHTTP.html

https://webfoundation.org/about/vision/history-of-the-web/

理解本真的REST架构风格

Architectural Styles and the Design of Network-based Software Architectures