01-HTTP简史

0.1. HTTP的诞生

20 世纪 60 年代,美国国防部高等研究计划署(ARPA)建立了 ARPA 网,它有四个分布在各地的节点,被认为是如今互联网的“始祖”。

20 世纪 70 年代,基于对 ARPA 网的实践和思考,研究人员发明出了著名的 TCP/IP 协议。

20 世纪 80 年代中期,具有良好封层结构和稳定性的 TCP/IP 协议进入了 UNIX 系统内核,促使更多的计算机接入了互联网。

1989 年,Tim Berners-Lee 发表论文,提出在互联网上构建超链接文档系统的构想。这篇论文中确立了三项关键技术。

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

基于此诞生了万维网(World Wide Web)。

0.1.1. HTTP/0.9

20 世纪 90 年代初期,互联网世界非常简陋,计算机处理能力低,存储容量小,网速很慢。网络上绝大多数的资源都是纯文本,很多通信协议也都使用纯文本,所以 HTTP 的设计也不可避免地受到了时代的限制。这一时期的 HTTP 被定义为 0.9 版,结构比较简单,为了便于服务器和客户端处理,它也采用了纯文本格式。

Tim Berners-Lee 最初设想的系统里的文档都是只读的,所以只允许用“GET”动作从服务器上获取 HTML 文档,并且在响应请求之后立即关闭连接,功能非常有限。

0.1.2. HTTP/1.0

1992 年发明了 JPEG 图像格式。

1993 年,NCSA开发出了 Mosaic,是第一个可以图文混排的浏览器。

1995 年开发出了服务器软件 Apache,简化了 HTTP 服务器的搭建工作。

1995 年发明了 MP3 音乐格式。

从用户需求的角度促进了 HTTP 的发展。

1996 年正式发布 HTTP/1.0 版本(HTTP/1.0 并不是一个“标准”,相当于一个“备忘录”),增强了0.9版本。

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

0.1.3. HTTP/1.1

1995 年,网景的 Netscape Navigator 和微软的 Internet Explorer 开始了著名的“浏览器大战”,这再一次极大地推动了 Web 的发展,HTTP/1.0 也在这个过程中经受了实践检验。

1999 年,HTTP/1.1 发布了 RFC 文档,编号为 2616(它是一个“正式的标准”,而不是一份可有可无的“参考文档”),正式确立了延续十余年的传奇。

这意味着今后互联网上所有的浏览器、服务器、网关、代理等等,只要用到 HTTP 协议,就必须严格遵守这个标准,相当于是互联网世界的一个“立法”。

HTTP/1.1 主要的变更点有:

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

HTTP/1.1 的推出开启了后续的“Web 1.0”“Web 2.0”时代。

2014 年对庞大且复杂的 HTTP/1.1 做了一次修订,被拆分成了六份较小的文档,编号为 7230-7235,优化了一些细节,没有任何实质性的改动。

0.1.4. HTTP/2

HTTP/1.1 发布之后的十几年间也出现了一些对 HTTP 不满的意见,主要就是连接慢,无法跟上迅猛发展的互联网,但 HTTP/1.1 标准一直“岿然不动”,无奈之下只好发明各式各样的“小花招”来缓解这些问题,比如以前常见的切图、JS 合并等网页优化手段。

Google 开发了浏览器 Chrome,然后推出了新的 SPDY 协议,并在 Chrome 里应用于自家的服务器,从实际的用户方来“倒逼”HTTP 协议的变革,这也开启了第二次的“浏览器大战”,Chrome 目前的全球的占有率超过了 60%,借此顺势把 SPDY 推上了标准的宝座。

2015 年互联网标准化组织以 SPDY 为基础制定新版本 HTTP 协议 发布了 HTTP/2,RFC 编号 7540。

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

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

HTTP/2 衍生出了 gRPC 等新协议,目前普及率比较低,大多数网站使用的仍然还是 20 年前的 HTTP/1.1

0.1.5. HTTP/3

在 HTTP/2 还处于草案之时,Google 又发明了一个新的协议,叫做 QUIC,依托它的庞大用户量和数据量,持续地推动 QUIC 协议成为互联网上的“既成事实”。

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

0.2. HTTP的含义

HTTP(超文本传输协议):

http

0.2.1. 协议

首先,HTTP 是一个协议,必须要有两个或多个参与者,也就是“协”,协议是对参与者的一种行为约定和规范,也就是“议”。

协议意味着有多个参与者为了达成某个共同的目的而站在了一起,除了要无疑义地沟通交流之外,还必须明确地规定各方的“责、权、利”,约定该做什么不该做什么,先做什么后做什么,做错了怎么办,有没有补救措施等等。

HTTP 是一个用在计算机世界里的协议。它使用计算机能够理解的语言确立了一种计算机之间交流通信的规范,以及相关的各种控制和错误处理方式

0.2.2. 传输

计算机和网络世界里有数不清的各种角色:CPU、内存、总线、磁盘、操作系统、浏览器、网关、服务器……这些角色之间相互通信也必然会有各式各样、五花八门的协议,用处也各不相同,例如广播协议、寻址协议、路由协议、隧道协议、选举协议等等。

HTTP 是一个“传输协议”,所谓的“传输”(Transfer),就是把一堆东西从 A 点搬到 B 点,或者从 B 点搬到 A 点,即“A<===>B”。

0.2.2.1. 双向协议

HTTP 协议是一个“双向协议”。有两个最基本的参与者 A 和 B,从 A 开始到 B 结束,数据在 A 和 B 之间双向而不是单向流动。

  • 通常把先发起传输动作的 A 叫做请求方
  • 把后接到传输的 B 叫做应答方或者响应方

0.2.2.2. 中转

数据虽然是在 A 和 B 之间传输,但并没有限制只有 A 和 B 这两个角色,允许中间有“中转”或者“接力”。

这样,传输方式就从“A<===>B”,变成了“A<=>X<=>Y<=>Z<=>B”,A 到 B 的传输过程中可以存在任意多个“中间人”,而这些中间人也都遵从 HTTP 协议,只要不打扰基本的数据传输,就可以添加任意的额外功能,例如安全认证、数据压缩、编码转换等等,优化整个传输过程。

HTTP 是一个在计算机世界里专门用来在两点之间传输数据的约定和规范

0.2.3. 超文本

所谓“文本”(Text),就表示 HTTP 传输的不是 TCP/UDP 这些底层协议里被切分的杂乱无章的二进制包(datagram),而是完整的、有意义的数据,可以被浏览器、服务器这样的上层应用程序处理。

在互联网早期,“文本”只是简单的字符文字,但发展到现在,“文本”的涵义已经被大大地扩展了,图片、音频、视频、甚至是压缩包,在 HTTP 眼里都可以算做是“文本”。

所谓“超文本”,就是“超越了普通文本的文本”,它是文字、图片、音频和视频等的混合体,最关键的是含有“超链接”,能够从一个“超文本”跳跃到另一个“超文本”,形成复杂的非线性、网状的结构关系。

对于“超文本”,我们最熟悉的就应该是 HTML 了,它本身只是纯文字文件,但内部用很多标签定义了对图片、音频、视频等的链接,再经过浏览器的解释,呈现在我们面前的就是一个含有多种视听信息的页面。

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

HTTP 是一个协议,是一种计算机间通信的规范,所以它不存在“单独的实体”,是一种“动态的存在”,是发生在网络连接、传输超文本数据时的一个“动态过程”。

编程语言是人与计算机沟通交流所使用的语言,而 HTTP 是计算机与计算机沟通交流的语言,我们无法使用 HTTP 来编程,但可以用编程语言去实现 HTTP,告诉计算机如何用 HTTP 来与外界通信。

在互联网世界里,HTTP 通常跑在 TCP/IP 协议栈之上,

  • 依靠 IP 协议实现寻址和路由、
  • TCP 协议实现可靠数据传输、
  • DNS 协议实现域名查找、
  • SSL/TLS 协议实现安全通信。

此外,还有一些协议依赖于 HTTP,例如 WebSocket、HTTPDNS 等。这些协议相互交织,构成了一个协议网,而 HTTP 则处于中心地位。

0.3. HTTP相关概念

与 HTTP 相关的各种应用,着重介绍互联网、浏览器、Web 服务器等常见且重要的概念。

http

0.3.1. 网络世界

实际的互联网是由许许多多个规模略小的网络连接而成的,这些“小网络”可能是只有几百台电脑的局域网,可能是有几万、几十万台电脑的广域网,可能是用电缆、光纤构成的固定网络,也可能是用基站、热点构成的移动网络……

互联网的正式名称是 Internet,里面存储着无穷无尽的信息资源,通常所说的“上网”实际上访问的只是互联网的一个子集“万维网”(World Wide Web),它基于 HTTP 协议,传输 HTML 等超文本资源,能力也就被限制在 HTTP 协议之内。

互联网上还有许多万维网之外的资源,例如常用的电子邮件、BT 和 Magnet 点对点下载、FTP 文件下载、SSH 安全登录、各种即时通信服务等等,它们需要用各自的专有协议来访问。

HTTP 协议灵活、易于扩展,且“超文本”的表述能力很强,很多其他原本不属于 HTTP 的资源也可以“包装”成 HTTP 来访问,这就是为什么能够总看到各种“网页应用”——例如“微信网页版”“邮箱网页版”——的原因。

0.3.2. 浏览器

浏览器的正式名字叫“Web Browser”,顾名思义,就是检索、查看互联网上网页资源的应用程序,名字里的 Web,实际上指的就是“World Wide Web”,也就是万维网。

浏览器本质上是一个 HTTP 协议中的请求方,使用 HTTP 协议获取网络上的各种资源。为了更好地检索查看网页,它还集成了很多额外的功能。例如:

  • HTML 排版引擎用来展示页面,
  • JavaScript 引擎用来实现动态化效果,甚至还有开发者工具用来调试网页,
  • 五花八门的各种插件和扩展。

在 HTTP 协议里,浏览器的角色被称为“User Agent”即“用户代理”,意思是作为访问者的“代理”来发起 HTTP 请求。不过在不引起混淆的情况下,通常都简单地称之为“客户端”。

0.3.3. Web服务器

浏览器是 HTTP 里的请求方,那么在协议另一端的应答方(响应方)就是服务器,Web Server。Web 服务器是 HTTP 协议里响应请求的主体,通常把控着绝大多数的网络资源,在网络世界里处于强势地位。

“Web 服务器”有两个层面的含义:硬件和软件。

  • 硬件含义:是物理形式或“云”形式的机器,在大多数情况下它可能不是一台服务器,而是利用反向代理、负载均衡等技术组成的庞大集群。但从外界看来,它仍然表现为一台机器,但这个形象是“虚拟的”。
  • 软件含义:是提供 Web 服务的应用程序,通常会运行在硬件含义的服务器上。它利用强大的硬件能力响应海量的客户端 HTTP 请求,处理磁盘上的网页、图片等静态文件,或者把请求转发给后面的 Tomcat、Node.js 等业务应用,返回动态的信息。

比起层出不穷的各种 Web 浏览器,Web 服务器就要少很多了,一只手的手指头就可以数得过来。

  • Apache 是老牌的服务器,到今天已经快 25 年了,功能相当完善,相关的资料很多,学习门槛低,是许多创业者建站的入门产品。
  • Nginx 是 Web 服务器里的后起之秀,特点是高性能、高稳定,且易于扩展。自 2004 年推出后就不断蚕食 Apache 的市场份额,在高流量的网站里更是不二之选。
  • 此外,还有 Windows 上的 IIS、Java 的 Jetty/Tomcat 等,因为性能不是很高,所以在互联网上应用得较少。

0.3.4. CDN

浏览器和服务器是 HTTP 协议的两个端点,浏览器通常不会直接连到服务器,中间会经过“重重关卡”,其中的一个重要角色就叫做 CDN。

CDN,全称是“Content Delivery Network(内容分发网络)”,它应用了 HTTP 协议里的缓存代理技术,代替源站响应客户端的请求。CDN 可以缓存源站的数据,让浏览器的请求不用“千里迢迢”地到达源站服务器,直接在“半路”就可以获取响应。

如果 CDN 的调度算法很优秀,更可以找到离用户最近的节点,大幅度缩短响应时间

CDN 也是现在互联网中的一项重要基础设施,除了基本的网络加速外,还提供负载均衡、安全防护、边缘计算、跨运营商网络等功能,能够成倍地“放大”源站服务器的服务能力,很多云服务商都把 CDN 作为产品的一部分。

0.3.5. 爬虫

浏览器是一种用户代理,代替我们访问互联网。HTTP 协议并没有规定用户代理后面必须是“真正的人类”,它也完全可以是“机器人”,这些“机器人”的正式名称就叫做“爬虫”(Crawler),实际上是一种可以自动访问 Web 资源的应用程序

据估计,互联网上至少有 50% 的流量都是由爬虫产生的,某些特定领域的比例还会更高,也就是说,如果你的网站今天的访问量是十万,那么里面至少有五六万是爬虫机器人,而不是真实的用户。

  • 爬虫绝大多数是由各大搜索引擎“放”出来的,抓取网页存入庞大的数据库,再建立关键字索引,这样我们才能够在搜索引擎中快速地搜索到互联网角落里的页面。

  • 爬虫不好的一面,会过度消耗网络资源,占用服务器和带宽,影响网站对真实数据的分析,甚至导致敏感信息泄漏。

“反爬虫”技术,通过各种手段来限制爬虫。其中一项就是“君子协定”robots.txt,约定哪些该爬,哪些不该爬。无论是“爬虫”还是“反爬虫”,用到的基本技术都是两个,一个是 HTTP,另一个就是 HTML。

0.3.6. HTML/WebService/WAF

HTML、WebService、WAF 等由于与 HTTP 技术上实质关联不太大。

  • HTML 是 HTTP 协议传输的主要内容之一,它描述了超文本页面,用各种“标签”定义文字、图片等资源和排版布局,最终由浏览器“渲染”出可视化页面。HTML 目前有两个主要的标准,HTML4 和 HTML5。广义上的 HTML 通常是指 HTML、JavaScript、CSS 等前端技术的组合,能够实现比传统静态页面更丰富的动态页面。
  • Web Service,它的名字与 Web Server 很像,但却是一个完全不同的东西。Web Service 是一种由 W3C 定义的应用服务开发规范,使用 client-server 主从架构,通常使用 WSDL 定义服务接口,使用 HTTP 协议传输 XML 或 SOAP 消息,也就是说,它是一个基于 Web(HTTP)的服务架构技术,既可以运行在内网,也可以在适当保护后运行在外网。因为采用了 HTTP 协议传输数据,所以在 Web Service 架构里服务器和客户端可以采用不同的操作系统或编程语言开发。例如服务器端用 Linux+Java,客户端用 Windows+C#,具有跨平台跨语言的优点。
  • WAF 近几年比较“火”是“网络应用防火墙”。与硬件“防火墙”类似,它是应用层面的“防火墙”,专门检测 HTTP 流量,是防护 Web 应用的安全技术。WAF 通常位于 Web 服务器之前,可以阻止如 SQL 注入、跨站脚本等攻击,目前应用较多的一个开源项目是 ModSecurity,它能够完全集成进 Apache 或 Nginx。

0.4. HTTP相关协议

各种 HTTP 相关协议,重点是 TCP/IP、DNS、URI、HTTPS 等。

http

0.4.1. TCP/IP

TCP/IP 协议是目前网络世界“事实上”的标准通信协议,实际上它是一系列网络通信协议的统称,其中最核心的两个协议是 TCP 和 IP,还有 UDP、ICMP、ARP 等,共同构成了一个复杂但有层次的协议栈。这个协议栈有四层:

  • 最上层是“应用层”
  • TCP 属于“传输层”
  • IP 属于“网际层”
  • 最下层是“链接层”

IP 协议是“Internet Protocol”的缩写,主要目的是解决寻址和路由问题,以及如何在两点间传送数据包。IP 协议使用“IP 地址”的概念来定位互联网上的每一台计算机。

  • 现在使用的 IP 协议大多数是 v4 版:地址是四个用“.”分隔的数字,例如“192.168.0.1”,总共有 2^32,大约 42 亿个可以分配的地址。
  • 又出现了 v6 版:使用 8 组“:”分隔的数字作为地址,容量扩大了很多,有 2^128 个。

TCP 协议是“Transmission Control Protocol”的缩写,意思是“传输控制协议”,它位于 IP 协议之上,基于 IP 协议提供可靠的(保证数据不丢失)、字节流形式(保证数据完整)的通信,是 HTTP 协议得以实现的基础。

在 TCP 协议的两端可以如同操作文件一样访问传输的数据,就像是读写在一个密闭的管道里“流动”的字节

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

0.4.2. DNS

TCP/IP 协议中使用 IP 地址来标识计算机,数字形式的地址便于计算机但对于人类来说不便。于是“域名系统”(Domain Name System)出现用有意义的名字来作为 IP 地址的等价替代。

在 DNS 中,“域名”(Domain Name)又称为“主机名”(Host),为了更好地标记不同国家或组织的主机,所以被设计成了一个有层次的结构。域名用“.”分隔成多个单词,级别从左到右逐级升高,最右边的被称为“顶级域名”。

对于顶级域名,例如:

  • 表示商业公司的“com”
  • 表示教育机构的“edu”
  • 表示国家的“cn”“uk”等

要使用 TCP/IP 协议来通信仍然要使用 IP 地址,所以需要把域名做一个转换,“映射”到它的真实 IP,这就是所谓的“域名解析”。域名解析的实际操作复杂很多,目前全世界有 13 组根 DNS 服务器,下面再有许多的顶级 DNS、权威 DNS 和更小的本地 DNS,逐层递归地实现域名查询。

HTTP 协议中并没有明确要求必须使用 DNS,但实际上为了方便访问互联网上的 Web 服务器,通常都会使用 DNS 来定位或标记主机名,间接地把 DNS 与 HTTP 绑在了一起。

0.4.2.1. 域名

域名是一个有层次的结构,是一串用“.”分隔的多个单词,最右边的被称为“顶级域名”,然后是“二级域名”,层级关系向左依次降低。最左边的是主机名,通常用来表明主机的用途,比如:

  • “www”表示提供万维网服务
  • “mail”表示提供邮件服务

不过这也不是绝对的,名字的关键是要让我们容易记忆。域名不仅能够代替 IP 地址,还有许多其他的用途。在 Apache、Nginx 这样的 Web 服务器里,域名可以用来标识虚拟主机,决定由哪个虚拟主机来对外提供服务,比如在 Nginx 里就会使用“server_name”指令:

server {
    listen 80;                       #监听80端口
    server_name  time.geekbang.org;  #主机名是time.geekbang.org
    ...
}

域名本质上还是个名字空间系统,使用多级域名就可以划分出不同的国家、地区、组织、公司、部门,每个域名都是独一无二的,可以作为一种身份的标识。因为这个特性,域名也被扩展到了其他应用领域,比如 Java 的包机制就采用域名作为命名空间,只是它使用了反序。而 XML 里使用 URI 作为名字空间,也是间接使用了域名。

域名的总长度限制在253个字符以内,而每一级域名长度不能超过63个字符,域名是大小写无关的,通常使用小写形式

0.4.2.2. 域名解析

就像 IP 地址必须转换成 MAC 地址才能访问主机一样,域名也必须要转换成 IP 地址,这个过程就是“域名解析”。

目前全世界网络上发生的 HTTP 流量,这些请求绝大多数都是基于域名来访问网站的,所以 DNS 就成了互联网的重要基础设施,必须要保证域名解析稳定可靠、快速高效。

DNS 的核心系统是一个三层的树状、分布式服务,基本对应域名的结构:

  • 根域名服务器(Root DNS Server):管理顶级域名服务器,返回“com”“net”“cn”等顶级域名服务器的 IP 地址
  • 顶级域名服务器(Top-level DNS Server):管理各自域名下的权威域名服务器,比如 com 顶级域名服务器可以返回 apple.com 域名服务器的 IP 地址
  • 权威域名服务器(Authoritative DNS Server):管理自己域名下主机的 IP 地址,比如 apple.com 权威域名服务器可以返回 www.apple.com 的 IP 地址

http

根域名服务器是关键,它必须是众所周知的,否则下面的各级服务器就无从谈起了。目前全世界共有 13 组根域名服务器,又有数百台的镜像,保证一定能够被访问到。

有了这个系统以后,任何一个域名都可以在这个树形结构里从顶至下进行查询,就好像是把域名从右到左顺序走了一遍,最终就获得了域名对应的 IP 地址。

例如,要访问“www.apple.com”,就要进行下面的三次查询:访问根域名服务器,它会告诉你“com”顶级域名服务器的地址;访问“com”顶级域名服务器,它再告诉你“apple.com”域名服务器的地址;最后访问“apple.com”域名服务器,就得到了“www.apple.com”的地址。

在核心 DNS 系统之外,还有两种手段用来减轻域名解析的压力,并且能够更快地获取结果,基本思路就是“缓存”。

首先,许多大公司、网络运行商都会建立自己的 DNS 服务器,作为用户 DNS 查询的代理,代替用户访问核心 DNS 系统。这些“野生”服务器被称为“非权威域名服务器”,可以缓存之前的查询结果,如果已经有了记录,就无需再向根服务器发起查询,直接返回对应的 IP 地址。这些 DNS 服务器的数量要比核心系统的服务器多很多,而且大多部署在离用户很近的地方。比较知名的 DNS 有:

  • Google 的“8.8.8.8”
  • Microsoft 的“4.2.2.1”
  • CloudFlare 的“1.1.1.1”

其次,操作系统里也会对 DNS 解析结果做缓存,如果你之前访问过“www.apple.com”,那么下一次在浏览器里再输入这个网址的时候就不会再跑到 DNS 那里去问了,直接在操作系统里就可以拿到 IP 地址。

另外,操作系统里还有一个特殊的“主机映射”文件,通常是一个可编辑的文本,在 Linux 里是“/etc/hosts”,在 Windows 里是“C:\WINDOWS\system32\drivers\etc\hosts”,如果操作系统在缓存里找不到 DNS 记录,就会找这个文件。

有了上面的“野生”DNS 服务器、操作系统缓存和 hosts 文件后,很多域名解析的工作直接在本地或本机就能解决,不仅方便了用户,也减轻了各级 DNS 服务器的压力,效率就大大提升了。

http

0.4.2.3. 域名新玩法

有了域名,又有了可以稳定工作的解析系统,就可以实现比 IP 地址更多的“新玩法”了。

第一种,“重定向”。域名代替了 IP 地址,可以让对外服务的域名不变,而主机的 IP 地址任意变动。当主机有情况需要下线、迁移时,可以更改 DNS 记录,让域名指向其他的机器,这样就可以保证业务服务不中断。

第二种,因为域名是一个名字空间,可以使用 bind9 等开源软件搭建一个内部DNS服务器。这样各种内部服务就都用域名来标记,发起网络通信时也就不必再使用写死的 IP 地址,可以直接用域名,比如:

  • 数据库服务都用域名“mysql.inner.app
  • 商品服务都用“goods.inner.app

第三种,基于域名实现的负载均衡

  • 第一种方式,因为域名解析可以返回多个 IP 地址,所以一个域名可以对应多台主机,客户端收到多个 IP 地址后,就可以自己使用轮询算法依次向服务器发起请求,实现负载均衡。

  • 第二种方式,域名解析可以配置内部的策略,返回离客户端最近的主机,或者返回当前服务质量最好的主机,这样在 DNS 端把请求分发到不同的服务器,实现负载均衡。

前面说的都是可信的 DNS,如果有一些不怀好意的 DNS,那么它也可以在域名这方面“做手脚”,弄一些比较“恶意”的“玩法”,举两个例子:

  • “域名屏蔽”,对域名直接不解析,返回错误,让你无法拿到 IP 地址,也就无法访问网站;
  • “域名劫持”,也叫“域名污染”,你要访问 A 网站,但 DNS 给了你 B 网站。

好在互联网上还是好人多,而且 DNS 又是互联网的基础设施,这些“恶意 DNS”并不多见,你上网的时候不需要太过担心。

0.4.3. URI/URL

DNS 和 IP 地址只是标记了互联网上的主机,但主机上有那么多文本、图片、页面,所以就出现了 URI(Uniform Resource Identifier,统一资源标识符),使用它就能够唯一地标记互联网上资源。

URI 另一个更常用的表现形式是 URL(Uniform Resource Locator,统一资源定位符), 也就是俗称的“网址”,它实际上是 URI 的一个子集,因为这两者几乎是相同的,差异不大,所以通常不会做严格的区分。

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

URI 主要有三个基本的部分构成:

  • 协议名:即访问该资源应当使用的协议,在这里是“http”;
  • 主机名:即互联网上主机的标记,可以是域名或 IP 地址,在这里是“nginx.org”;
  • 路径:即资源在主机上的位置,使用“/”分隔多级目录,在这里是“/en/download.html”。

举个例子,通过电话簿找到了小明,让他把昨天做好的宣传文案快递过来。那么这个过程中就完成了一次 URI 资源访问:

  • “快递”,就是你要访问这个资源的“协议名”
  • “小明”就是“主机名”
  • “昨天做好的宣传文案”就是“路径”

0.4.4. HTTPS

TCP/IP、DNS 和 URI 的“加持”之下,HTTP 协议终于可以自由地穿梭在互联网世界里,顺利地访问任意的网页。

HTTPS 全称是“HTTP over SSL/TLS”,也就是运行在 SSL/TLS 协议上的 HTTP。这里 SSL/TLS是一个负责加密通信的安全协议,建立在 TCP/IP 之上,所以也是个可靠的传输协议,可以被用作 HTTP 的下层。

因此 HTTPS 相当于“HTTP+SSL/TLS+TCP/IP”。

SSL 的全称是“Secure Socket Layer”,由网景公司发明,当发展到 3.0 时被标准化,改名为 TLS,即“Transport Layer Security”,但由于历史的原因还是有很多人称之为 SSL/TLS,或者直接简称为 SSL。

SSL 使用了许多密码学最先进的研究成果,综合了对称加密、非对称加密、摘要算法、数字签名、数字证书等技术,能够在不安全的环境中为通信的双方创建出一个秘密的、安全的传输通道。

0.4.5. 代理

代理(Proxy)是 HTTP 协议中请求方和应答方中间的一个环节,作为“中转站”,既可以转发客户端的请求,也可以转发服务器的应答。

代理有很多的种类,常见的有:

  • 匿名代理:完全“隐匿”了被代理的机器,外界看到的只是代理服务器;
  • 透明代理:它在传输过程中是“透明开放”的,外界既知道代理,也知道客户端;
  • 正向代理:靠近客户端,代表客户端向服务器发送请求;
  • 反向代理:靠近服务器端,代表服务器响应客户端的请求;

CDN,实际上就是一种代理,它代替源站服务器响应客户端的请求,通常扮演着透明代理反向代理的角色。

由于代理在传输过程中插入了一个“中间层”,所以可以在这个环节做很多有意思的事情,比如:

  • 负载均衡:把访问请求均匀分散到多台机器,实现访问集群化;
  • 内容缓存:暂存上下行的数据,减轻后端的压力;
  • 安全防护:隐匿 IP, 使用 WAF 等工具抵御网络攻击,保护被代理的机器;
  • 数据处理:提供压缩、加密等额外的功能。

关于 HTTP 的代理还有一个特殊的“代理协议”(proxy protocol),它由知名的代理软件 HAProxy 制订,但并不是 RFC 标准。

HTTP可以应用在UNIX Domain Socket上,它是一种进程间通信机制,也满足HTTP对下层的“可靠传输”要求,所以就成了“HTTP over UNIX Domain Socket”

0.5. 网络分层模型

0.5.1. TCP/IP网络分层模型

TCP/IP 设计时,创造性地提出了“分层”的概念,把复杂的网络通信划分出多个层次,再给每一个层次分配不同的职责,层次内只专心做自己的事情就好,用“分而治之”的思想把一个“大麻烦”拆分成了数个“小麻烦”,从而解决了网络通信的难题。

http

TCP/IP 协议总共有四层,每一层需要下层的支撑,同时又支撑着上层,任何一层被抽掉都可能会导致整个协议栈坍塌。它的层次顺序是“从下往上”数的,所以第一层就是最下面的一层。

  • 第一层叫“链接层”(link layer),负责在以太网、WiFi 这样的底层网络上发送原始数据包,工作在网卡这个层次,使用 MAC 地址(也称为局域网地址,唯一的标识一个网卡)来标记网络上的设备,也叫 MAC 层。
  • 第二层叫“网际层”或者“网络互连层”(internet layer),IP 协议就在这一层。 IP 协议定义了“IP 地址”的概念,所以在“链接层”的基础上,用 IP 地址取代 MAC 地址,把许许多多的局域网、广域网连接成一个虚拟的巨大网络,在这个网络里找设备时只要把 IP 地址再“翻译”成 MAC 地址就可以了。
  • 第三层叫“传输层”(transport layer),这个层次协议的职责是保证数据在 IP 地址标记的两点之间“可靠”地传输,是 TCP 协议工作的层次,另外还有它的一个“小伙伴”UDP。
  • 第四层叫“应用层”(application layer),由于下面的三层把基础打得非常好,所以在这一层有各种面向具体应用的协议。例如 Telnet、SSH、FTP、SMTP HTTP等。

  1. MAC 层的传输单位是帧(frame),
  2. IP 层的传输单位是包(packet),
  3. TCP 层的传输单位是段(segment),
  4. HTTP 的传输单位则是消息或报文(message)。

这些名词并没有什么本质的区分,可以统称为数据包。

IP 协议的职责是“网际互连”,它在 MAC 层之上,使用 IP 地址把 MAC 编号转换成了四位数字,这就对物理网卡的 MAC 地址做了一层抽象,发展出了许多的“新玩法”。例如,分为 A、B、C、D、E 五种类型,公有地址和私有地址,掩码分割子网等。只要每个小网络在 IP 地址这个概念上达成一致,不管它在 MAC 层有多大的差异,都可以接入 TCP/IP 协议栈,最终汇合进整个互联网。

在 IP 地址之上再来一次抽象,把数字形式的 IP 地址转换成更有意义更好记的名字,在字符串的层面上再增加“新玩法”。于是,DNS 域名系统就这么出现了。

0.5.1.1. TCP/UDP

  • TCP 是一个有状态的协议,需要先与对方建立连接然后才能发送数据,而且保证数据不丢失不重复。
  • UDP 比较简单无状态,不用事先建立连接就可以任意发送数据,但不保证数据一定会发到对方。

两个协议的另一个重要区别在于数据的形式。

  • TCP 的数据是连续的“字节流”,有先后顺序,
  • UDP 是分散的小数据包,是顺序发,乱序收。

0.5.2. OSI网络分层模型

http

  • 第一层:物理层,网络的物理形式,例如电缆、光纤、网卡、集线器等等;
  • 第二层:数据链路层,它基本相当于 TCP/IP 的链接层;
  • 第三层:网络层,相当于 TCP/IP 里的网际层;
  • 第四层:传输层,相当于 TCP/IP 里的传输层;
  • 第五层:会话层,维护网络中的连接状态,即保持会话和同步;
  • 第六层:表示层,把数据转换为合适、可理解的语法和语义;
  • 第七层:应用层,面向具体的应用传输数据。

TCP/IP 是一个纯软件的栈,没有网络应有的最根基的电缆、网卡等物理设备的位置。而 OSI 则补足了这个缺失,在理论层面上描述网络更加完整。

OSI 为每一层标记明确了编号,最底层是一层,最上层是七层,而 TCP/IP 的层次从来只有名字而没有编号。显然,在交流的时候说“七层”要比“应用层”更简单快捷,特别是英文,对比一下“Layer seven”与“application layer”。

0.5.3. 两个分层模型的映射关系

http

  • 第一层:物理层,TCP/IP 里无对应;
  • 第二层:数据链路层,对应 TCP/IP 的链接层;
  • 第三层:网络层,对应 TCP/IP 的网际层;
  • 第四层:传输层,对应 TCP/IP 的传输层;
  • 第五、六、七层:统一对应到 TCP/IP 的应用层。

这就是“理想与现实”之间的矛盾。理想很美好,有七层,但现实很残酷,只有四层,“多余”的五层、六层就这样“消失”了。

OSI 的分层模型在四层以上分的太细,而 TCP/IP 实际应用时的会话管理、编码转换、压缩等和具体应用经常联系的很紧密,很难分开。例如,HTTP 协议就同时包含了连接管理和数据格式定义。

  • 所谓的“四层负载均衡”就是指工作在传输层上,基于 TCP/IP 协议的特性,例如 IP 地址端口号等实现对后端服务器的负载均衡。
  • 所谓的“七层负载均衡”就是指工作在应用层上,基于 HTTP 协议解析 HTTP 报文里的 URI、主机名、资源类型等数据,再用适当的策略转发给后端服务器。

有一个辨别四层和七层比较好的(但不是绝对的)小窍门,“两个凡是”:

  1. 凡是由操作系统负责处理的就是四层或四层以下
  2. 凡是需要由应用程序(也就是你自己写代码)负责处理的就是七层

TCP/TP协议栈之外,还有一些协议位于OSI的第五层和第六层,例如UNIX Domain Socket就可以认为是在第五层。

0.5.4. TCP/IP协议栈的工作方式

HTTP 协议的传输过程就是通过协议栈逐层向下,每一层都添加本层的专有数据,层层打包,然后通过下层发送出去。接收数据则是相反的操作,从下往上穿过协议栈,逐层拆包,每层去掉本层的专有头,上层就会拿到自己的数据。

下层的传输过程对于上层是完全“透明”的,上层也不需要关心下层的具体实现细节,所以就 HTTP 层次来看,它不管下层是不是 TCP/IP 协议,看到的只是一个可靠的传输链路,只要把数据加上自己的头,对方就能原样收到。

http

上次修改: 14 April 2020