📚 第一章 网络基础知识
📄 一句话概括

互联网普及的分水岭不是「能连上」,而是「随便一个域名都能解析出来」。 域名系统把「人记的名字」翻译成「机器认的地址」,这层翻译是普及的地基。

📝 本节和前面几节的关系

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 秒实验

  1. 把同一个域名解析 10 次,看耗时是不是越来越稳定。
  2. 试试解析一个不存在的域名(如 no-such-host-36.invalid),看抛什么异常、耗时多少。
  3. 用 socket.gethostbyname 代替 getaddrinfo,看返回值的形状有什么不同。

常见误区

  1. 以为 DNS 就是「一张大表」。 它是分层的分布式系统,没有一台机器知道全部, 每台只知道该问谁。
  2. 以为域名解析失败就是「网断了」。 DNS 服务器不可达也会失败,此时 IP 层可能是通的。 用 IP 直连试试就能区分。
  3. 以为 DNS 只解析一次。 每次新建连接都可能解析,除非程序自己缓存。 这就是「DNS 缓存」在各种框架里反复出现的原因。
自测三问(点开对答案) 1. 为什么 DNS 要做成分布式,而不是一个大数据库? —— **规模与单点问题**:全网域名数量太大,集中存储既装不下也扛不住查询;而且一个点挂了全网就瘫。 **分层查询把负载分散到各级服务器。** 2. 递归查询与迭代查询的区别是什么? —— **递归是「你替我查到底」,迭代是「你告诉我下一步问谁」。**末端机器用递归, 本地 DNS 往上用迭代。 3. 解析一个域名很快,可能是什么原因? —— **本地有缓存**。操作系统、浏览器、本地 DNS 都可能缓存过。**要测真实解析耗时,得先清缓存。**

下一节讲普及之后的事:网络不再是「一个功能」,而是「所有功能的底座」。

相关笔记