互联网普及的分水岭不是「能连上」,而是「随便一个域名都能解析出来」。 域名系统把「人记的名字」翻译成「机器认的地址」,这层翻译是普及的地基。
1.2.4 讲的是地址怎么发,这一节讲地址怎么被人记住。 1.2.6 会讲「普及之后发生了什么」:网络从一件专门的工具变成所有软件的底座。
一、IP 地址为什么记不住
183.60.118.213 这串数字没有任何语义,既不对应行业,也不对应地区,更不对应人名。
而人记东西靠的是「结构」与「意义」——这两样 IP 地址都不给。
| 对象 | 例子 | 人能记住吗 |
|---|---|---|
| IP 地址 | 183.60.118.213 |
记不住,也没有规律 |
| 域名 | www.qq.com |
能,有层次 |
| URL | https://www.qq.com/a.html |
能,从左往右读 |
第二行那个「有层次」是关键:com 是顶级域、qq 是机构、www 是主机,
从右往左越来越具体。
这种「倒着读」的结构不是为了好看,它让「同一类的名字」在字符串上挨在一起,
查起来可以分层查。
二、DNS 是怎么被设计出来的
最早的做法是一张表:把所有主机名与 IP 的对应关系写在一个文件里,
每台机器都存一份(hosts 文件至今还在)。
表一长就崩了——机器数按指数涨,没人能维护一张全局表。
| 方案 | 能撑多少台 | 问题 |
|---|---|---|
| 单张 hosts 表 | 几百台 | 同步不过来 |
| 集中式数据库 | 几千台 | 一个点扛不住 |
| 分布式分层查询 | 上亿 | 要靠缓存 |
第三行那个「分布式分层」是 DNS 的核心设计:没有一台机器知道全部,但每一台知道「该问谁」。 这个思路和路由表一模一样:不需要记住全世界,只需要记住「下一跳」。 所以 DNS 的查询过程是「逐级往下问」:根服务器 → 顶级域服务器 → 权威服务器。
三、查询的两条路
同一个问题「www.qq.com 的 IP 是多少」,有两种问法:
| 方式 | 做法 | 负载在哪 |
|---|---|---|
| 递归查询 | 服务器替你问到底 | 服务器重 |
| 迭代查询 | 服务器只告诉你下一步问谁 | 客户端重 |
现实里是混合的:你的机器问本地 DNS 用递归(我就想知道答案), 本地 DNS 往上问用迭代(我自己一级一级问)。 这个分工不是随意定的: 末端设备笨、数量多,让它只发一次请求;中间的 DNS 服务器少、能力强,让它多跑几趟。 这种「把复杂度放在少数节点上」的思路,在网络里到处都是——CDN、代理、网关,都是同一个套路。
四、动手 Demo:互联网普及到什么程度,量一个 DNS 解析
真解析三个域名,各量三次,看解析出的 IP 与耗时。 第一次往往最慢——因为要递归查;后面有本地缓存,快很多。
import socket, time
for nm in ('www.onvif.org', 'www.python.org', 'www.qq.com'):
ts = []
ip = '-'
for _ in range(3):
t0 = time.perf_counter()
try:
info = socket.getaddrinfo(nm, 443, socket.AF_INET)
ip = info[0][4][0]
except Exception as e:
ip = '失败:' + type(e).__name__
ts.append((time.perf_counter() - t0) * 1000)
print('%-16s %-16s 最快%5.1f 最慢%5.1f ms'
% (nm, ip, min(ts), max(ts)))
实跑输出:
--------------------------------------------------------------------
互联网普及到什么程度,量一个 DNS 解析
--------------------------------------------------------------------
**互联网普及最直观的指标是「随便一个域名能不能解析出来」。**下面真解析三个域名,各量三次。
域名 解析出的 IPv4 最快ms 最慢ms
---------------------------------------------------------
www.onvif.org 190.92.159.115 0.9 3.6
www.python.org 151.101.128.223 0.7 0.9
www.qq.com 183.60.118.213 0.8 0.9
**域名解析是「互联网普及」的隐形基础设施**:**人记名字、机器认地址,中间这层翻译就是 DNS。**
**注意最快与最慢能差好几倍**——第一次要递归查,后面有本地缓存。
**本机测到的是「本机 → 本地 DNS」这一段,再往上的递归段看不到。**
三个域名的耗时都在毫秒级,说明本机有缓存、或者本地 DNS 就在附近。
onvif.org 解析出 190.92.159.115——
这个地址不在国内,所以后面 Demo 11 连它 443 端口要几十毫秒。
getaddrinfo 返回的是一个列表,可能有多条记录(负载均衡就是这么做的),这里只取第一条。
要看清缓存的作用,得先清缓存再测——清 DNS 缓存需要管理员权限,本机做不到,
所以这里没给「冷查询」的数。
30 秒实验
- 把同一个域名解析 10 次,看耗时是不是越来越稳定。
- 试试解析一个不存在的域名(如
no-such-host-36.invalid),看抛什么异常、耗时多少。 - 用
socket.gethostbyname代替getaddrinfo,看返回值的形状有什么不同。
常见误区
- 以为 DNS 就是「一张大表」。 它是分层的分布式系统,没有一台机器知道全部, 每台只知道该问谁。
- 以为域名解析失败就是「网断了」。 DNS 服务器不可达也会失败,此时 IP 层可能是通的。 用 IP 直连试试就能区分。
- 以为 DNS 只解析一次。 每次新建连接都可能解析,除非程序自己缓存。 这就是「DNS 缓存」在各种框架里反复出现的原因。
自测三问(点开对答案)
1. 为什么 DNS 要做成分布式,而不是一个大数据库? —— **规模与单点问题**:全网域名数量太大,集中存储既装不下也扛不住查询;而且一个点挂了全网就瘫。 **分层查询把负载分散到各级服务器。** 2. 递归查询与迭代查询的区别是什么? —— **递归是「你替我查到底」,迭代是「你告诉我下一步问谁」。**末端机器用递归, 本地 DNS 往上用迭代。 3. 解析一个域名很快,可能是什么原因? —— **本地有缓存**。操作系统、浏览器、本地 DNS 都可能缓存过。**要测真实解析耗时,得先清缓存。**下一节讲普及之后的事:网络不再是「一个功能」,而是「所有功能的底座」。
- ☐ (本节完,下一节 1.2.6 以互联网技术为中心的时代)