What lies behind a URL
可视化演示:01 · 一次 HTTPS 请求。 | 网络请求可视化
先问你一个问题:
从你在浏览器里输入一个网址、按下回车,到网页出现在屏幕上,你觉得中间发生了几步?
很多人的直觉答案是:一步。输入网址,网页就出来了。看起来确实如此。但在这短短几秒里发生的事情,比你想象的多得多。这篇文章就把它一层一层拆开来看。
一
现在,我给你一个地址:
www.example.com
这个东西叫做什么?它叫:域名。域名可以简单理解成:方便人类记忆和使用的一种名字。为什么需要名字?你可以想象一下:如果我告诉你“去找一个叫张三的人”,你可能很容易就找到了;但如果我告诉你“去找身份证号为 xxx…xxx 的人”,你可能就要花上一段时间了(这里我们忽略人名的重复性)。这是因为,人对有意义的文字的记忆,远比对一串数字的记忆轻松。所以你可以把域名大致理解为人名。
那人名的对照物——身份证号——在网络里叫什么?这就是马上要出场的新概念:IP 地址。以后你会经常见到它。和人类相反,计算机处理和计算数字更顺手:网站背后真正要找的,是一台连在网络上的计算机或网络服务,而计算机网络里,通常就用 IP 地址来标识每一台设备。一个 IP 地址可能长这样:142.250.xxx.xxx。你不需要记住这个具体数字,只需要记住结论:域名方便人记忆,IP 地址适合计算机进行网络通信。所以:
人
↓
www.example.com
↓
DNS
↓
IP地址
↓
找到目标服务器
这里又出现了一个新的东西:DNS。DNS 可以简单理解成:互联网里的“电话簿”。你知道一个人的名字,通过电话簿查到他的电话号码;类似地,你知道一个网站的域名,通过 DNS 查到它对应的 IP 地址。不妨想象一个没有域名的世界:你上网必须直接输入 IP 地址。想访问学校官网?对不起,网址是“xxx.xxx.xxx.xxx”——大概会带来不少困扰。
还有一个问题:如果哪天网站换了一台服务器,IP 变了怎么办?你记住的所有地址都可能失效。所以实际上,我们需要把两个东西分开:人记得住的名字,和网络通信需要的地址。这就是域名和 IP 分开存在的意义之一。于是,当你输入 www.example.com,浏览器或者系统就要想办法知道:“这个名字对应哪个 IP?”这一步由 DNS 完成:域名 → IP 地址。这一步完成之后,电脑才真正知道:要去网络中的哪里寻找这个服务。
二
我们的电脑找到了服务器。但这里又出现一个问题:服务器虽然是一台电脑,但一台电脑上可能同时运行很多程序。比如一台服务器上可能同时运行:
- 一个网站;
- 一个游戏服务器;
- 一个数据库;
- 一个聊天机器人;
- 一个文件服务。
那么问题来了:你到底要找哪一个?这时候我们会遇到:端口。你现在不需要深入理解端口。可以先把它理解成:一栋大楼里的不同房间。IP地址帮助我们找到:哪一栋楼。端口帮助我们找到:哪一个房间。那这个房间号是谁定的?其实是访问的人定的:你要访问什么样的服务,就默认去敲对应的那个房间的门。而每个服务都会提前守在自己的房间里,等着有人来敲门。所以可以简单理解为:
域名
↓
找到IP
↓
找到服务器
↓
找到对应端口
↓
找到对应服务
你会发现,原本我们以为“打开一个网页”是一件非常简单的事情,但现在,它已经被拆成了好几层。
三
现在,我们已经找到了服务器,也知道该找哪个服务。那接下来呢?服务器总不能自己猜。所以你的电脑需要向服务器发送一个请求:浏览器告诉服务器需要什么,服务器把对应的数据返回给你。这个过程就是:请求 → 响应
英文就是:
Request → Response
这是互联网中非常重要的一种基本模式。
你现在就可以自己验证一下:随便打开一个网页,按下 F12(Mac 上是 Cmd + Option + I),切换到 Network(网络)面板,然后刷新页面。你会看到一长串条目——每一条,就是一次真实的请求,和它对应的响应。
你可能会有点奇怪:我明明只打开了一个网页,为什么冒出来几十条请求?因为一个网页并不是一次请求就搬完的。HTML 本身是一条;页面里的每张图片、每个样式文件、每个脚本,都是各自单独的一条请求。
那服务器返回的到底是什么?对网页来说,主要是一堆代码。最核心的是三样:
- HTML:结构。这个网页里有什么内容,按什么骨架组织。
- CSS:外观。这些东西长什么样、什么颜色、怎么排版。
- JS(JavaScript):行为。点这个按钮会发生什么,内容怎么动态变化。
你的浏览器获取到服务器回复的响应后,会把这些代码解析、渲染,并将最终的画面展示给你。想亲眼看看的话:在任意网页上右键“查看网页源代码”,看到的那一大片,就是 HTML。
这里有一条很重要的分界线,值得现在就记下来:HTML、CSS、JS 这些代码,是在你的浏览器里运行的,这一侧叫前端;而在服务器上处理请求的那个程序,叫后端。同样是“代码”,跑的地方完全不同。这对词你以后会反复遇到。
四
到目前为止,我们一直只盯着 www.example.com 这一小段看。但现在你已经认识了:域名、端口、请求和响应。是时候把一个完整的网址拆开看一遍了:
https://www.example.com:443/articles/3?page=2
从左到右,每一部分都有名字和分工:
https:协议。规定这次交流按什么“规矩”来:数据是什么格式、要不要加密。这个 https 具体是什么意思,下一节马上会讲到。www.example.com:域名。老朋友了。:443:端口。不写的话,就按协议的默认值来:https 默认 443,http 默认 80。/articles/3:路径。表示你要的是这台服务器上的哪个东西。它就像电脑里的文件夹路径,/是最顶层。?page=2:查询参数。问号后面,是你随请求附带的条件:“我要第 2 页。”
所以一个网址其实是一句完整的话:用 https 的规矩,去找 example.com 的默认房间,要里面的 /articles/3 这个东西,条件是 page 等于 2。
平时你感觉不到这些部分的存在,因为浏览器会帮你把地址补全、填好。但以后你会越来越频繁地见到它们——尤其在出问题的时候,答案经常就藏在你以为“只是一串网址”的东西里。
五
现在我们把刚才所有东西串起来。
假设你在浏览器输入:
https://www.example.com
然后按下回车。
顺便说一句:地址开头的 https,那个 S 是 Secure(安全)的意思。HTTP 就是上面说的“请求 → 响应”这套规则本身;HTTPS 则是在这之上加了一层加密:你和服务器之间来回传送的数据都是加密过的,就算有人在途中截获,看到的也只是一堆看不懂的乱码。这就是为什么浏览器会在地址栏给你画一把小锁。
大致可以理解成:浏览器看到 www.example.com(端口不写的话,就按前面说的默认规则来),通过 DNS 查询知道它对应什么 IP。得到了 IP 地址,就知道了要找网络中的哪台服务器。下一步是建立网络连接,找到对应的服务,然后浏览器向服务器发送请求:“请把这个网页给我。”服务器收到请求、处理请求,再把网页相关的数据通过网络传回来。浏览器收到数据,解析、处理、渲染——最后,网页出现在你的屏幕上。所以我们最开始看到的:“输入网址 → 网页出现”
实际上可以拆成:
输入网址
↓
域名
↓
DNS
↓
IP地址
↓
服务器
↓
请求
↓
服务器处理
↓
响应
↓
浏览器处理
↓
网页出现
现在你可以数一数:从输入网址到网页出现,中间至少有七八步。回到开头的问题——和你当初猜的比呢?
六
到这里,整个流程已经串起来了。但知道流程有什么用?我们换个角度再用一次。
假设有一天,你打开一个网页,它加载不出来了。大多数人的反应到这里就结束了:刷新,再刷新,重启,放弃。
但你现在已经知道:网页出现,是很多个环节接力的结果。域名要被解析成 IP,服务器要能找到,连接要能建立,请求要发得出去,服务器要能处理,响应要回得来。任何一环断了,你看到的现象都是同一个:网页打不开。
所以“网页打不开”其实不是一个问题,而是一类问题。你可以顺着链条问下去:
网页打不开
↓
换个浏览器 / 无痕模式,还不行?
↓
别的网页能打开吗?(网络本身有问题吗?)
↓
DNS 解析成功了吗?
↓
IP 能访问吗?服务器还活着吗?
↓
请求发出去了吗?服务器处理得了吗?
每一环坏掉,表现其实是不一样的:DNS 解析失败,浏览器会很快告诉你“找不到这个网站”;服务器关机了,你的请求就像敲门没人应,要等到超时才报错。同样是“打不开”,背后的原因完全不同。
还有一个东西能帮你更快地定位问题:状态码。服务器返回的每一个响应,都带一个三位数的编号,相当于这次交流的“体检报告”。不用记具体数字,先看第一位,它代表大类:
- 2 开头:成功。最常见的是 200:一切正常,数据给你。
- 3 开头:搬家了。比如 301:你要的东西换了地址,浏览器会自动跑去新地址拿。你平时几乎察觉不到,只会看到地址栏里的网址悄悄变了。
- 4 开头:问题大概率在你这边。最著名的是 404:服务器找到了,但你要的那个东西不存在——路径写错了、文件根本没部署上去、甚至只是大小写打错了,都会 404。还有 403:东西在,但你不被允许看。
- 5 开头:问题在对方。500 是服务器程序自己出错了;502 / 504 是服务器应了门,但它后面的程序挂了、或者迟迟不回话。以后你自己往服务器上部署东西的时候,这两个会经常见到。
在刚才的 Network 面板里,每条请求旁边就写着它的状态码。下次网页不对劲,先看一眼首位数字
有兴趣的话,可以回到开头那个可视化演示,把整个流程再对照着走一遍。
七
对于一些“看似”没必要去了解的问题,如果你很幸运地有时间,不妨去试试。你在这个过程中积累的知识、经验和手段,会成为你将来遇到必须解决的问题时的支撑。
最后,把这一篇真正想留给你的一句话放在这里:
看到现象,不要停在现象;继续问“为什么”。
今天拆的是“打开一个网页”。但你身边到处都是这样的现象:消息是怎么发出去的、扫码为什么能付上钱、Wi-Fi 为什么会断。下一次遇到“打不开”“没反应”,先别急着刷新,试着问一句:到底是哪一环断了?