速成课 · No. 14

每一次页面加载,机器之间都在进行一场快速而精确的对话:找到彼此的地址,开通一条线路,提出一个问题,再把答案封进一个别人都读不到的信封里。这一切都不是魔法——它只是几个清晰的想法,顶着吓人的名字。学会这些名字,整个 Web 就变得读得懂了。

只讲精髓 · 每个想法一个画面 · 掌握术语

§ 01

剥掉术语,网络就是一件简单的事:机器互相发送消息。其余的一切,都是关于这些消息如何找到去路、又如何保持可靠的细节。

计算机靠传纸条来对话

一套庞大的邮政系统:任何一栋楼都能给任何另一栋楼递一张纸条,只要它在信封上写对地址。

网络不过是连接起来、好让彼此发送数据的计算机。数据以小小的数据包传送——就像被拆成一张张明信片的纸条,每一张都标着它从哪来、往哪去。互联网就是把这件事放大到行星尺度:数十亿台机器,任何一台都能把一个数据包递给任何另一台。这就是全部的根基;剩下的,是我们如何让它变得可靠而有意义。

每台机器都有一个地址——它的 IP

地球上每一栋楼都有独一无二的邮政地址。没有它,邮差就无处投递,也无处回信。

要让一个数据包抵达,目的地需要一个地址。那就是 IP 地址——一个标识机器在网络中身份的数字,比如 142.250.74.78。每台联网的设备都有一个。当你的笔记本发出一个请求时,它会盖上自己的 IP 作为回信地址,好让答案知道该回到哪里。没有地址,就没有对话。

客户端发问,服务器作答

一间餐厅和一间厨房。一边点单;另一边备好再送回来。这顿饭里,角色是固定的。

Web 的大部分都跑在客户端—服务器模型上。客户端(你的浏览器、你的应用)发出一个请求;服务器(一台运行着网站或服务的机器)送回一个响应。你的手机是客户端,问「把这个页面给我」;某处的服务器用那个页面来回答。把这一对关系记牢——下面的每个想法,都是为了让这场「请求与响应」运转起来。

网络就是机器在传递写好地址的消息。客户端发问,服务器作答——其余的一切,都是让这件事变得可靠。

§ 02

你敲下一个名字,比如 example.com,可网络只会把路由指向数字。总得有什么东西,把你记得住的名字翻译成机器需要的地址。那个东西就是 DNS。

名字是给人的;数字是给机器的

你靠名字记住朋友,可电话系统只拨号码——于是你留着一份联系人名单,把一个变成另一个。

人们记得住 wikipedia.org;网络需要一个像 198.35.26.96 这样的 IP 地址。域名是对人友好的标签;IP 是对机器友好的地址。这两者必须被关联起来,因为没人愿意背号码,也没有路由器能按名字来路由。弥合这道鸿沟的,是一整套系统,它在每一次点击中不停地、隐形地运转着。

DNS 是互联网的电话簿

一本巨大的、永远开着门的名录:你给它一个名字,它把要拨的号码递回给你。你从不见它干活——你只是拿到了号码。

DNS——域名系统——就是把域名翻译成对应 IP 地址的服务。在你的浏览器能去取 example.com 之前,它先问 DNS「这个名字的地址是什么?」,然后拿回一个数字。这次查询(也叫解析)每一次都先发生,只在毫秒之间。正是这个并不光鲜的步骤,让人类读得懂的网址成为可能。

答案会被缓存,下一次就快了

你查一次朋友的号码,把它记在便利贴上——下一次你只要看那张贴纸,而不必再翻开整本名录。

每个名字都从头查一遍会很慢,所以 DNS 的答案会被缓存——由你的浏览器、你的操作系统和你的网络记住一阵子。地址附带一个 TTL(存活时间),说明在再次核对之前,它可以安全复用多久。这就是为什么你访问过的站点能瞬间载入它的地址,也是为什么一次 DNS 变更需要时间才能扩散开来。

DNS 就是电话簿:它把你记得住的名字变成网络需要的 IP 地址,再把它缓存起来,好让下一次瞬间完成。

§ 03

知道地址,和真正展开一场对话不是一回事。在消息可靠地流动之前,两台机器先开通一条连接——并约定好该敲服务器的哪一「扇门」。

TCP 是一条可靠、有序的线路

一通带确认的电话:你说一句话,对方说「收到」,在每一部分都被确认并按序到位之前,什么都不会往下走。

TCP(传输控制协议)是可靠发送数据最常用的方式。它通过一次快速的握手开通连接(双方都同意对话),然后保证每个数据包都按序到达,丢失的会被重发。你拿一点速度,换来「没有任何东西被丢弃或打乱」的保障。Web、电子邮件,以及大多数应用,正是为了那份可靠才跑在 TCP 上。

UDP 用可靠性换速度

在嘈杂的房间里大声喊出最新消息——有些词会丢,但你不会停下来逐字确认,因为跟上节奏比抓住每一个字更要紧。

UDP 是那个快、却不作保证的替代方案:它不握手就把数据包打出去,丢了也不重发。你失去可靠性,但换来速度和低开销,对直播视频、语音通话和游戏来说,这正是对的取舍——掉一帧无所谓,但等待不行。知道这两者都存在,就明白网络里始终有这么一个「速度对可靠」的旋钮。

端口是机器上编了号的门

一栋楼,许多门,每扇门都为某个用途编了号——送货走 80 号门,办公室走另一扇。同一个地址,不同的入口。

一台机器跑着许多服务,所以光有 IP 地址还不够——你还需要一个端口,一个挑出该找哪个服务的数字。按惯例,Web 流量用端口 80(HTTP)或 443(HTTPS);数据库可能监听另一个端口。地址把你带到那栋楼;端口把你带到对的那扇门。IP 加端口合在一起,才点名出一个确切的目的地。

TCP 是一条可靠、有序的线路;UDP 又快又会丢包。IP 找到那栋楼,端口挑出那扇门。

§ 04

线路一旦开通,双方就需要一种共同的语言来发问和作答。在 Web 上,这种语言就是 HTTP——一种为每一次请求和回复定下的、简单而严格的格式。

HTTP 就是请求与响应

一来一回的正式信件:一封结构清晰的请求寄出去,一封结构清晰的回复寄回来,各自都遵循同一套约定好的格式。

HTTP(超文本传输协议)是 Web 的语言。客户端发出一个请求——它想要什么——服务器送回一个响应——结果。每一个页面、每一张图片、每一次 API 调用,都是这样的一次往来。它基于文本、有结构,正因如此,这么多工具才都能说它。把一次请求和响应的形态掌握透,你就懂了整个 Web 是怎么流动的。

方法说明你想做什么

在图书馆柜台:你可以借一本书、还一本书,或者请求添一本新的。同一个柜台,不同的意图——工作人员对每一种的处理也不同。

每个请求都有一个方法——那个动词。GET 取数据(载入一个页面)。POST 送新数据(提交一个表单)。PUT 更新某样东西;DELETE 删除它。方法让服务器一眼看出你的意图,行为端正的系统会区别对待它们——GET 永远不该改动任何东西,而 POST 被预期会。这些动词是 API 设计方式的脊梁。

头部承载细节;主体承载货物

一个信封,外面写着些备注——给谁的、里面是什么、该怎么处理——以及里头那封真正的信。

每个请求和响应都有头部——一行行带标签的元数据,比如内容类型、语言、谁在发问,还有认证令牌——以及一个可选的主体,也就是真正的载荷(往上送的表单数据,回来的页面或 JSON)。头部是双方在不碰货物的情况下,协商各种细节的方式。一次往来里大部分的「怎么做」,都住在头部里。

状态码告诉你结果如何

给回复用的红绿灯:绿灯放行,重定向指向别处,红灯告诉你哪里出了错——以及是谁的错。

每个响应都带一个状态码2xx 表示成功(200 OK)。3xx 是重定向(去那边看看)。4xx 表示客户端错了——404 Not Found403 Forbidden——是问错了。5xx 表示服务器错了——500——是坏了。读第一个数字,你立刻就知道它有没有成功、是谁的错、该往哪儿看。这是 Web 上最有用的那一项调试技能。

HTTP 在两次请求之间就把你忘了

一个对你上次到访毫无记忆的柜台办事员——你每次走上前,都得重新自我介绍,再把票据出示一遍。

HTTP 是无状态的:每个请求都独自成立,默认情况下服务器对上一个请求什么都不记得。所以要保持登录,每个请求都必须带上「你是谁」的凭证——头部里的一个 cookie 或一枚令牌。正是无状态,让 Web 能扩展到数十亿次请求,而理解了它,就能解释为什么你的身份会随着每一次调用一起捎带过去。

HTTP 就是请求与响应:用方法表意图,用头部装细节,用主体载货物,再用一个状态码精确告诉你结果如何。

§ 05

朴素的 HTTP 是一张明信片——任何经手的人都能读到。HTTPS 是同一场对话,封进一个只有对的那台服务器才能打开的信封里,还签了名,好让你知道在跟谁说话。

加密把消息封起来

把一张读得到的明信片,换成一个只有收件人握着钥匙的上锁箱子——快递员一路搬着它,却没有一个人能读到里面装的什么。

HTTPS 就是用 TLS 包了一层加密的 HTTP。它把内容打乱,让你和服务器之间的任何人——你咖啡馆的 Wi-Fi、一家互联网服务商、一个攻击者——只看到一堆乱码,而不是你的密码或消息。地址栏里那个锁形图标,意味着这道封印就位了。在现代 Web 上,它是默认设置,因为一场没封上的对话,就是一场任何人都能读的对话。

证书证明你在跟谁说话

一本由受信任的权威机构查验过的护照——它证明这个人正是他所声称的那个人,而不是一个顶着他名字的冒充者。

光有加密还不够;你还需要知道那台服务器真的是 yourbank.com,而不是个冒牌货。证书是一份数字身份证,由受信任的证书颁发机构签发,它证明一台服务器拥有它所声称的那个名字。你的浏览器会自动核对它,并在它缺失或不对时向你发出警告。正是这一点,挡住了攻击者——哪怕是在一条加密连接上——冒充某个站点。

为什么那把挂锁要紧

这是两件事的区别:寄一封封好、且经过验证的信,和在挤满人的房间里大声喊出你的银行账户信息。

没有 HTTPS,网络路径上的任何人都能读取、甚至篡改你的流量——一个man-in-the-middle,悄无声息地坐在你和服务器之间。有了它,消息被封上,发件人也被验证。这就是为什么登录页、支付,乃至如今几乎一切,都用 HTTPS,也是为什么浏览器把朴素的 HTTP 标记为「不安全」。那把挂锁是个小图标,代表着一份很大的保证。

HTTPS 用加密把消息封起来,用证书证明服务器的身份——隐私与信任,都在一把挂锁里。

§ 06

Web 感觉起来是即时的,可距离和物理定律始终在收过路费。两个词——延迟和带宽——就解释了大部分「为什么快、为什么慢」。

延迟是等待;带宽是宽度

一根水管:第一滴水多久才到,是一回事;每秒能流过多少,是另一回事。再宽的管子,水也要先有个延迟才能流到那一头。

延迟是响应开始前的那段等待——一条消息来回往返的时间。带宽是你每秒能搬动多少数据。它俩相互独立:一条连接可以是高带宽,却又是高延迟。大文件下载在乎带宽;一个利落、灵敏的站点在乎延迟。把这两者搞混,正是为什么「我的网很快,可这站点感觉很慢」会让人摸不着头脑。

每一次往返都要花钱,而距离是真实的

向另一块大陆上的某个人问一个问题:哪怕以光速,这一来一回也有一个你打不破的下限。

一个发往遥远服务器的请求,要做一次物理上的往返,而即便是光,跨越行星也并非即时——一趟横跨世界的往返,有一个数十毫秒的硬下限。更糟的是,载入一个页面往往需要许多次往返。这就是为什么话痨式的设计在距离面前显得迟缓,也是为什么「减少往返次数」是存在已久的性能技巧之一。

用 CDN 把答案放得更近

一本热门书,被各地的本地图书馆都备上货,而不是只有一座你必须寄信去借的中央档案馆——离你近的那本,到得快得多。

CDN(内容分发网络)是一支遍布世界各地的服务器队伍,把你内容的副本放在离用户近的地方。当东京的某人载入你的站点时,他是从附近的一座城市得到服务的,而不是从隔着一片海的你的源服务器——这把延迟大幅砍掉。CDN 就是把缓存用到了地理上,全球性的站点之所以在哪儿都感觉像本地的,靠的就是它。

负载均衡器把工作分摊开

银行里的排队管理员,把顾客引向任何一个空着的柜员,于是没有哪一个窗口被挤爆,而别的窗口闲着。

当一台服务器扛不住所有流量时,一个负载均衡器就坐在好几台前面,把请求分摊到它们身上。大站点正是靠它来应对数百万用户——在均衡器后面加更多服务器——也靠它在一台服务器宕机时撑下去,因为均衡器只要绕开它来路由就行。这个词精确地描述了它干的事:它在均衡负载。

延迟是等待;带宽是宽度。距离总在收过路费——CDN 把答案放得更近,负载均衡器把工作分摊开。

§ 07

现在,跟着一次点击——从地址栏到渲染出的页面——把每个词都串到一起。如果你能把这个讲出来,你就懂了 Web 是怎么对话的。

当你载入一个 URL 时,发生了什么

一封信完整的旅程:查地址、开通线路、封好信封、提出问题、拿到回复——全都在远不到一秒之间。

你敲下 example.comDNS 把名字变成一个 IP 地址。你的浏览器在端口 443 上向那个 IP 开通一条 TCP 连接,双方做一次 TLS 握手,好让线路被加密、服务器的证书被核对。在那条封好的线路上,你的浏览器送出一个 HTTP GET 请求;服务器用一个状态码和一个主体来回复。页面可能来自附近的一个 CDN,以削减延迟。你的浏览器读取响应,把页面画出来。这门课里的每一个术语,都不过是给那平凡的一秒中的某一步命了名。

这趟旅程,按顺序
  • DNS 把域名解析成一个 IP 地址。 - 一条 TCP 连接在某个端口上向那个 IP 开通(HTTPS 用 443)。 - 一次 TLS 握手把线路加密,并核对服务器的证书。 - 客户端送出一个 HTTP 请求——一个方法、若干头部,也许还有一个主体。 - 服务器返回一个状态码、若干头部和一个主体。 - 一个 CDN 可能就近提供它;一个负载均衡器可能挑出那台服务器。
你现在拥有的词
  • IP 地址 / 数据包 —— 机器的地址,以及数据赖以传送的那些小块。 - DNS / TTL —— 名字到数字的查询,以及答案被缓存多久。 - TCP / UDP / 端口 —— 可靠的线路、快速的线路,以及机器上的哪扇门。 - HTTP / 方法 / 头部 / 主体 / 状态码 —— 那门请求-响应的语言。 - HTTPS / TLS / 证书 —— 那个封好、经过验证的信封。 - 延迟 / 带宽 / CDN / 负载均衡器 —— 等待、宽度,以及规模如何对抗这两者。
Web 如今讲得通了的迹象
  • 一个 404 对上一个 500,立刻就告诉你是你、还是服务器的错。 - 「网很快但站点很慢」读作一个延迟问题,而非带宽问题。 - 那把挂锁意味着既加密身份已验证——你知道它保证了什么。 - 你能解释为什么保持登录,需要在每一个无状态请求上都带一个 cookie。 - 你能不看就把上面那整段 URL 旅程讲出来。

载入一个页面,就是一场快速的对话:找到地址,开通线路,封好它,发问,作答。每一个吓人的词,都不过是那一秒里的某一步。

速成课结束 · 7 章 · 掌握术语

接下来是练习:打开你浏览器的开发者工具,切到 Network 标签页,载入任意一个站点。看着真实的请求一个个冒出来——那些方法、那些状态码、那些头部、那些时序——把每一个都对上这门课里的一个词。当你亲眼看着它们发生的那一刻,那些抽象就变得具体了。但请把一个想法举过其余之上:Web 不是魔法。它是机器在找一个地址、开通一条线路、把它封好,再用一个问题换回一个答案——而现在,每一步你都有词可说了。