URL 第一次出门问路

URL 抱着域名跑遍网络问路处,得到的回答却永远是“去问下一位”。正准备投诉全员踢皮球,一张真正的服务器地址突然从最后一扇窗口递了出来。

分享
URL 第一次出门问路

只有名字,没有门牌号

本文承接上一篇:《像素工地返工记》

“谁知道这个名字对应哪栋楼?”

URL 抱着一块写有 www.example.com 的域名牌,站在像素工地门口。

布局工人摇头。

绘制工人摇头。

合成员也摇头,顺手把大门关了一半。

“等等!” URL 抵住门,“总得告诉我该往哪儿走吧?”

“沿走廊直走,网络问路处。” HTML 解析器从门缝里递出一张号票,“到了先取号。”

“这里只有名字,没有地址,能取到网页吗?”

“不能。”

“那刚才为什么不早说?”

“刚才忙着看卷尺打结。”

门“砰”地关上了。

URL 低头检查行李:

方案:https
主机:www.example.com
端口:默认 443
路径:/news

该带的都带了。

唯独没有服务器的网络地址。

URL 叹了口气,抱着域名牌走向网络问路处。刚拐过弯,TCP 老司机从车库里探出头来。

“去哪儿?要发车了。”

“去 www.example.com。”

“地址。”

URL 举起域名牌。

TCP 老司机眯着眼看了三秒:“这是名字。”

“很有名的名字。”

“再有名也不能写进目的地址栏。” 老司机拍了拍车门,“网络传输要找到目标主机,得拿到可用的 IP 地址。先去问 DNS,问清楚再回来。”

“DNS 是谁?”

车库深处传来一声悠长的广播:

“请——先——查——本——地——记——录——”

URL 抬头:“谁在说话?”

“网络问路处的叫号机。” 老司机缩回车里,“嗓门大,脾气慢,去吧。”

第一站就在眼皮底下

网络问路处没有想象中热闹。

只有三扇窗口。

第一扇写着浏览器旧地址簿,第二扇堆满系统档案,第三扇坐着一位戴耳机的 DNS 递归解析器。

URL 直奔第三扇。

“您好,请问 www.example.com 住哪儿?”

递归解析器刚抬起头,前两扇窗口同时敲响玻璃。

“排队!”

浏览器地址簿管理员先翻开本子。

“这个名字最近来过吗?”

“第一次出门。”

“那就是没有。” 管理员啪地合上本子,“下一位。”

URL 不服:“连查都没查!”

“空白页要查多久?”

第二扇窗口里,系统管理员推来一摞档案:“近期查过的地址,操作系统和本地解析设施也可能留有一份。”

管理员又踢了踢桌角的铁皮柜:“还有这里。像 hosts 文件里的静态主机名映射,也可能直接写好名字该去哪里。”

“那快看看。”

系统管理员翻了一圈,也合上档案:“没有。”

“又没有?”

“没有就是没有,难道现场编一个?”

URL 指向三扇窗口:“所以每次出门都得挨个查?”

递归解析器摘下一边耳机:“先说好,有的浏览器自己记,有的更多交给系统,检查顺序也会因实现而不同。眼前这三扇窗口只是常见过程的简化摆法,别出去说所有设备都必须这样排队。”

URL 小声嘀咕:“还挺严谨。”

“不严谨就会把包裹送进别人家厨房。”

系统管理员拍拍档案:“反正本地要是已经有没过期的答案,今天就不用派人去外面跑腿。”

“今天什么都没有呢?”

三扇窗口同时转向递归解析器。

递归解析器慢慢戴正耳机。

“那就轮到我跑腿了。”

这位窗口真的会跑腿

URL 把域名牌塞进窗口:“拜托查到底,我赶着取网页。”

递归解析器接过牌子,盖下一枚章:

查询:www.example.com
需要:A / AAAA 记录

“这两个是什么?”

A 记录给出 IPv4 地址,AAAA 记录给出 IPv6 地址。”

“为什么 AAAA 有四个 A?”

“命名历史问题。”

“不能叫 B 吗?”

“今天只负责查地址,不负责重命名互联网。”

递归解析器推开侧门,跨上一辆摩托车。

URL 也要往后座爬。

“下来。”

“不是一起问吗?”

“你把完整问题交给我,等最终答案就行。后面该问谁、问几次,由我处理。”

“要是他们不理你呢?”

“换可用的服务器、重试,或者最后告诉你解析失败。总之不是把半张地图塞给你,让你自己流浪。”

油门一响,递归解析器冲进了夜色。

URL 趴在窗口上喊:“一定要问到底啊!”

远处传来一句:“这就叫递归服务——”

“听不见!”

“坐回去等——”

根窗口只给下一站

递归解析器的第一站,是一座巨大的圆形问路台。

台子四周挂满域名,最中央只有一个小小的点:.

根域名服务器值班员坐在里面,正在给一沓指路条盖章。

递归解析器递上问题:“www.example.com 的地址是什么?”

值班员扫了一眼:“不知道。”

“不知道?”

“嗯。”

“那我跑这么远干什么?”

“别急。” 值班员从抽屉里抽出一张条子,“com 这一片归这些顶级域名服务器管,去问它们。”

递归解析器接过条子:“所以没有最终地址。”

“根区负责告诉你顶级域名该往哪里问,不负责背下所有主机地址。”

“那您刚才直接说‘下一站’不行吗?”

“每天都有人先问我‘知不知道’。”

“您可以优化话术。”

“你可以优化路线。”

两位对视三秒。

递归解析器把投诉表又塞回口袋,骑车前往 com 问路处。

com 也不给最终答案

com 顶级域名服务器窗口排着长队。

example.comshop.comnews.com 的问路员各举各的牌子,挤得像一筐域名后缀。

终于轮到递归解析器。

“请问 www.example.com 的地址——”

“不知道。”

窗口里的管理员回答得非常熟练。

递归解析器按住口袋里的投诉表:“又不知道?”

“但知道 example.com 的权威 DNS 服务器在哪里。” 管理员递出一张新的指路条,“找它。那边保管这个域名区域的正式记录。”

“根窗口让我找你,你又让我找别人。”

“这叫分工。”

“从摩托车上看,像踢皮球。”

“要不要最终答案?”

“要。”

“那就继续骑。”

递归解析器抓起纸条,再次冲进夜色。

根服务器先把查询引向 com 顶级域名服务器,com 再把查询引向 example.com 的权威 DNS。每一站管理自己那一段委派关系,不需要保存全世界所有域名的最终地址。

递归解析器原本觉得大家在互相推诿。

骑到第三站时,忽然觉得这套制度至少省柜子。

最后一位终于翻开账本

example.com 权威 DNS 的门不大,里面的档案柜倒是顶到了天花板。

递归解析器把域名牌放上柜台:“www.example.com,查地址。”

权威管理员戴上手套,从柜子里抽出一张记录。

“找到了。”

递归解析器差点鼓掌:“终于有人知道!”

“先别急。这张不是地址。”

纸上写着:

www.example.com.  CNAME  edge.example.net.

“又是下一站?” 递归解析器把头盔往桌上一放,“这次准备把我指到哪个大洲?”

CNAME 表示这个名字是另一个规范名称的别名。” 权威管理员敲了敲记录,“要找 www.example.com,继续解析 edge.example.net。”

“为什么不直接写 IP?”

“别名可以让多个名字指向另一套名称安排。后面的目标地址改变时,使用别名的一方不必都改成同一批 IP。”

“听起来方便。”

“骑车的人未必这么想。”

递归解析器重新戴上头盔,抓着 edge.example.net 冲出门。

这次路线熟了。先找到负责 net 的顶级域名服务器,再顺着新指路条找到 example.net 的权威 DNS。

几张指路条往柜台上一拍,example.net 的权威管理员从档案柜里抽出两张记录:

edge.example.net.  A     192.0.2.10
edge.example.net.  AAAA  2001:db8::10

递归解析器盯着记录看了半天。

“这次真是地址?”

“真是。”

“后面没有‘请问下一位’?”

“没有。”

“能盖章吗?”

权威管理员盖下红章:最终地址记录。

递归解析器长舒一口气。

“提醒一句。” 管理员把记录递出窗口,“真实查询不一定都会遇到 CNAME。权威服务器也可能直接返回所问名称的 AAAAA 记录。”

“也就是说,今晚绕路纯属这个名字自己安排的?”

“可以这么客观地说。”

地址旁边还有保质期

递归解析器正要走,权威管理员又从窗口里伸出一只手。

“回来。”

“还有下一站?”

“有 TTL。”

记录旁边还有一行数字:

TTL: 300

“地址还有五分钟试用期?”

TTL 是记录允许被缓存的时间提示,单位是秒。缓存可以在这段时间内复用答案,不必每次都从头查询。”

“五分钟后服务器就搬家?”

“不一定。五分钟后只是缓存不能继续把旧副本当作有效答案,需要重新查询。新答案可能没变,也可能已经变了。”

递归解析器在记录背面写下到期时间。

CNAME 和地址记录都一样保五分钟?”

“每条记录有各自的 TTL,缓存时分别计算。别拿一张标签贴整条链。”

“该回去了。”

问一次,记一阵

递归解析器回到网络问路处时,URL 已经趴在窗口前睡着了。

“醒醒,地址查到了。”

URL 猛地坐直:“谁给的?根服务器?”

“根服务器给 com 的方向,com 给权威服务器的方向,权威服务器给正式记录。中途碰到 CNAME,又继续把别名解析到地址。”

“所以大家真的只知道下一站?”

“多数时候返回的是委派线索,最后由负责相应 DNS 区域的权威服务器给出答案。整个过程由我替你跑完。”

递归解析器把 AAAAA 记录推过窗口。

URL 把两张地址卡塞进口袋,转身就跑。

“回来!”

“又怎么了?”

“缓存。”

递归解析器复印了一份答案,放进自己的地址簿,并标好到期时间。系统和浏览器也可能在各自的层级保存可复用结果。

“下一个 URL 再来问同一个名字,只要答案还有效,就不必重演今晚的公路片。”

“那以后永远用这张?”

“TTL 到期后重新问。缓存的具体行为还可能受到实现策略影响,不能把 TTL 当成保证某条记录必定存满这么久的定时锁。”

URL 抱紧地址卡:“懂了。名字交给你,你替我一路问到地址,再按 TTL 留一阵答案。”

“差不多。” 递归解析器抬起印章,“只要别再说 TTL 决定服务器什么时候搬家。”

URL 护住脑袋:“这次真记住了。”

终于可以发车

TCP 老司机已经在车库门口等得喝完了两杯咖啡。

URL 远远举起地址卡:“查到了!”

“名字。”

www.example.com。”

“地址。”

URL 把 192.0.2.102001:db8::10 拍到车门上。

“这才像话。” TCP 老司机翻了翻两张卡,“还一次给了两个。”

“选哪张?”

“连接调度会结合当前网络、地址是否可用和连接策略尝试合适的地址。” 老司机把卡片收好,“不是 DNS 在窗口随手圈一个,就让全世界排队走同一扇门。”

URL 又翻开行李:“那 /news443 呢?DNS 怎么没盖章?”

“IP 告诉网络该找哪台主机,端口告诉我该去哪个服务入口。” 老司机点了点 443,“这个等连接时用。”

TCP 老司机接过后续连接任务,网络部门也开始准备把请求送往目标主机。URL 刚爬上车,又从口袋里摸出域名牌。

“既然已经有 IP,这块牌子是不是可以扔了?”

HTTP 抱着请求单从车库另一边跑来,一把按住域名牌:“不能扔!”

“地址不是已经查到了吗?”

“地址给网络部门找主机,名字还没退休。” HTTP 把域名牌夹进请求单,“安全连接和后续 HTTP 请求都还会用到主机名,/news 也得放进后面的请求里。”

“所以 DNS 只会查 IP?”

“DNS 能查不同类型的记录。” HTTP 拍了拍 TCP 刚收好的地址卡,“只是刚才这趟,主要任务是为主机名找到可连接的地址。”

URL 从请求单里抽回域名牌:“行,那就一起带着。”

车门刚要关,隔壁返程通道突然响起海关警报。

另一趟请求刚从不同的站点运回一箱数据,JavaScript 老大追在后面冲出通道:“服务器都把货送回来了,为什么不交给我?”

浏览器海关拦在通道中央,抖开一张来源登记表:

“这箱货来自另一个源。通关许可呢?”

URL 一只脚还踩在车门上:“原来问清地址还不够,别人的货回来还得过海关?”

TCP 老司机默默松开车门按钮。

第三杯咖啡,大概也要凉了。