系列: 从 0 开始学习计算机网络
适合读者: 计算机专业学生、网络基础薄弱的开发者、Java 后端学习者
本文关键词: DNS、域名解析、A 记录、AAAA 记录、CNAME、递归查询、迭代查询、TTL、nslookup、dig
一、引言:为什么访问网站时输入域名,而不是 IP 地址?
日常开发中,我们访问网站时通常输入:
https://api.example.com/users/1
而不是记住服务器的 IP 地址。原因之一是域名更容易阅读和管理,但网络通信最终需要把目标主机名解析为可用于连接的地址信息。
**DNS(Domain Name System,域名系统)**就是负责把域名映射到相关记录的分布式命名系统。最常见的场景是查询域名对应的 IP 地址,不过 DNS 还保存邮件路由、别名和其他类型的记录。
本文会从浏览器访问域名的场景出发,解释 DNS 查询的层级结构、递归解析器的工作过程、DNS 缓存与 TTL,并介绍在 Windows 和 Linux 上如何排查域名解析问题。
二、DNS 是什么?
可以把 DNS 理解成互联网的“分布式电话簿”:人们输入易读的域名,DNS 帮助找到相关的网络地址或其他信息。
DNS 不是一台中央服务器保存全世界所有域名,而是由多个层级和大量分布式服务器共同维护。不同域名的记录由相应的权威 DNS 服务器管理。
几个重要术语:
- 域名(Domain Name): 例如
api.example.com。 - DNS 记录(Resource Record,RR): DNS 中保存的一条信息,例如域名对应的 IPv4 地址。
- 递归解析器(Recursive Resolver): 代表客户端完成解析过程的 DNS 服务,常由网络服务商、企业网络或公共 DNS 服务提供。
- 权威 DNS 服务器(Authoritative Name Server): 对某个 DNS 区域中的记录提供权威答案的服务器。
- TTL(Time To Live): DNS 记录可被缓存的时间限制。
三、常见 DNS 记录有哪些?
| 记录类型 | 用途 | 示例说明 |
|---|---|---|
| A | 将名称映射到 IPv4 地址 | api.example.com → 192.0.2.10 |
| AAAA | 将名称映射到 IPv6 地址 | api.example.com → 2001:db8::10 |
| CNAME | 将一个名称指向另一个规范名称 | www.example.com → site.example.com |
| MX | 指定域名的邮件交换服务器 | 邮件系统查找投递目标 |
| NS | 指定某个 DNS 区域的权威名称服务器 | 指示应向哪些权威服务器查询 |
| TXT | 保存文本形式的信息 | 常用于域名验证及邮件安全配置等场景 |
表中的 IP 地址使用了文档示例网段或示意值,不代表真实网站的当前解析结果。
补充两点:
- CNAME 指向的是另一个域名,而不是直接指向 IP 地址;解析器通常还需要继续查询目标名称的记录。
- 一个域名可以对应多条记录。DNS 返回哪些地址取决于记录配置、查询类型和解析策略,不保证永远只返回一个 IP。
四、DNS 查询是如何完成的?

4.1 第一步:应用先尝试使用已有解析结果
浏览器、操作系统或本地 DNS 组件可能已经缓存了域名对应的结果。如果缓存仍然有效,可能不需要重新访问外部 DNS 服务器。
缓存的具体位置和查找顺序取决于操作系统、浏览器和应用实现,因此不要把所有设备都理解为完全相同的固定流程。
4.2 第二步:向递归解析器查询
如果本地没有可用结果,客户端通常会向配置好的递归解析器发送查询请求。递归解析器负责继续完成查找,并把最终结果返回给客户端。
客户端通常不需要自己逐个查询根服务器、顶级域服务器和权威服务器;这些步骤一般由递归解析器处理。
4.3 第三步:递归解析器查找所需记录
如果递归解析器的缓存也没有可用答案,它可能按照 DNS 层级继续查询:
- 查询根 DNS 服务器,获取下一层(例如
.com)的委派信息。 - 查询对应的顶级域(TLD)DNS 服务器,获取目标域名所在区域的权威服务器信息。
- 查询该域名区域的权威 DNS 服务器,获得 A、AAAA、CNAME 等相关记录。
- 缓存符合条件的结果,并将答案返回给客户端。

注意:图中的“根 → 顶级域 → 权威服务器”是帮助理解的一种简化路径。真实解析可能涉及 CNAME 链、额外的地址查询、缓存命中、DNSSEC 验证等情况;根服务器通常返回委派线索,而不是直接保存所有最终域名的地址记录。
五、递归查询和迭代查询有什么区别?
这两个词很容易混淆。
- 递归查询: 客户端要求 DNS 服务器代为完成解析,并返回最终结果或错误。
- 迭代查询: 被查询的服务器返回自己能提供的答案,或者给出下一步应该询问的服务器线索。
在常见的解析过程中,客户端向递归解析器提出递归请求,而递归解析器在向 DNS 层级服务器查找时,通常使用迭代方式逐步获取答案。
可以类比为:
- 递归:你请一位工作人员帮你查到最终结果,工作人员负责跑完流程。
- 迭代:工作人员每问一个部门,部门只告诉他答案或下一个应该去的部门。
这个类比只是帮助理解角色分工;DNS 协议中的具体行为由查询标志、响应内容和服务器配置决定。
六、DNS 缓存与 TTL:为什么第二次访问可能更快?
DNS 查询可能经过多层缓存。缓存的目标是减少重复查询、降低延迟和减轻 DNS 基础设施的负担。

6.1 TTL 是什么?
TTL 是一条 DNS 记录允许被缓存的时间限制,通常以秒为单位。例如,若某条记录的 TTL 为 300,缓存接收方可在符合协议规则的情况下缓存该记录最多 300 秒。
TTL 不是“网站只能访问 300 秒”,也不是 HTTP 页面缓存时间。它控制的是 DNS 记录缓存的有效期。
6.2 修改 DNS 记录后,为什么有时不会立即生效?
假设域名的 A 记录从地址 A 改成地址 B:
- 某些解析器可能已经缓存旧记录;
- 在旧记录 TTL 尚未到期前,解析器可能继续返回旧结果;
- 不同递归解析器、操作系统或应用的缓存状态可能不同;
- TTL 到期后,新的查询通常会重新获取记录,但仍需考虑各层缓存和配置。
因此,修改 DNS 记录不意味着全球所有客户端会在同一时刻切换到新地址。部署迁移时应提前规划 TTL,并观察解析情况。
6.3 DNS 缓存和 HTTP 缓存不是一回事
| 对比项 | DNS 缓存 | HTTP 缓存 |
|---|---|---|
| 缓存内容 | 域名相关的 DNS 记录 | HTTP 响应内容或表示 |
| 常见控制信息 | DNS 记录 TTL | Cache-Control、ETag、Last-Modified 等 |
| 主要目的 | 减少重复域名查询 | 减少重复内容传输或重新生成 |
| 例子 | 缓存 api.example.com 的地址记录 | 缓存网页、图片或接口响应 |
即使 DNS 命中缓存,客户端仍可能需要建立 TCP/TLS 连接并发送 HTTP 请求;DNS 缓存命中不代表整个网页内容也从缓存中读取。
七、DNS 使用 UDP 还是 TCP?
初学者经常听到“DNS 使用 UDP 53 端口”,但这句话并不完整。
- DNS 传统查询通常使用 UDP 端口 53,适合大多数常见查询。
- DNS 也可以使用 TCP 端口 53,例如响应被截断后需要通过 TCP 重试,或用于区域传送等场景。
- 现代环境还可能使用 DoT(DNS over TLS) 或 DoH(DNS over HTTPS),分别通过 TLS 或 HTTPS 保护 DNS 查询传输;具体端口和网络路径取决于部署方式。
所以,更准确的表述是:DNS 既可以使用 UDP,也可以使用 TCP;此外还有通过 TLS 或 HTTPS 传输 DNS 的方案。
八、如何在本机排查 DNS 解析问题?
当网站打不开时,先不要直接认定是服务器宕机。可能的原因包括 DNS 解析失败、网络不通、端口未开放、TLS 握手失败或 HTTP 服务异常。
8.1 Windows:使用 nslookup
查询域名:
nslookup api.example.com
指定 DNS 服务器查询:
nslookup api.example.com 1.1.1.1
第二条命令要求向指定的 DNS 服务器查询,但是否能成功取决于网络策略和该服务器的可达性。这里不预设或编造具体输出。
8.2 Linux / macOS:使用 dig
查询 A 记录:
dig api.example.com A
查询 AAAA 记录:
dig api.example.com AAAA
查询指定解析器:
dig @1.1.1.1 api.example.com A
如果系统没有安装 dig,可以使用系统已有的 nslookup,或按操作系统的软件包管理方式安装 DNS 查询工具。
8.3 常见现象怎么理解?
- 返回 IP: 当前查询获得了相应记录,但不代表目标服务的端口一定可连接。
- NXDOMAIN: DNS 响应表示查询的名称不存在;仍需检查域名拼写、区域配置及实际响应来源。
- 超时: 可能是解析器不可达、网络策略阻断或 DNS 服务未及时响应,不等于域名一定不存在。
- 解析到旧 IP: 检查 TTL、递归解析器和本机缓存;还要确认权威 DNS 记录是否已正确更新。
排查时应分清 DNS 解析、网络连通性、TCP 连接、TLS 握手和 HTTP 响应,这是定位线上问题的基本思路。
九、Java 后端如何进行域名解析?
Java 可以通过 InetAddress 获取主机名对应的地址信息:
import java.net.InetAddress;
import java.util.Arrays;
public class DnsLookupDemo {
public static void main(String[] args) throws Exception {
InetAddress[] addresses =
InetAddress.getAllByName("example.com");
Arrays.stream(addresses)
.map(InetAddress::getHostAddress)
.forEach(System.out::println);
}
}
9.1 代码说明
InetAddress.getAllByName(...):请求解析主机名,并返回可用的地址对象数组。getHostAddress():读取地址的文本表示。- 返回结果可能包含 IPv4、IPv6 地址,具体取决于域名记录、系统网络配置和解析环境。
不要把这段代码当作 DNS 协议抓包工具。 它调用 Java 与操作系统提供的名称解析机制,可能受到系统配置和缓存影响,并不保证每次调用都会向公共 DNS 服务器发送一次查询。
生产环境还要关注 DNS 结果缓存、连接池中的连接生命周期、服务发现和故障切换策略。若排查的是 Java 服务连接问题,应该同时确认“解析出的地址是什么”和“应用实际连接到了哪个地址”。
十、常见误区
误区 1:DNS 只负责把域名转换成 IPv4 地址
不完整。A 记录对应 IPv4,AAAA 对应 IPv6;DNS 还支持 CNAME、MX、NS、TXT 等多种记录。
误区 2:客户端每次访问域名都会从根服务器开始查
不对。浏览器、操作系统或递归解析器可能已经缓存了可用结果;只有需要进一步解析时,才可能继续查询 DNS 层级服务器。
误区 3:DNS 记录 TTL 到期,网站就无法访问
不对。TTL 控制缓存有效期,不是网站可访问时长。记录到期后通常需要重新解析。
误区 4:DNS 只使用 UDP
不对。DNS 也使用 TCP;此外还存在 DoT、DoH 等传输方式。
误区 5:域名解析成功就说明网站正常
不对。解析成功只说明获取到了相关 DNS 答案,后续仍可能遇到路由、端口、TCP、TLS、HTTP 或应用层问题。
十一、本篇总结
- DNS 是分布式命名系统,用于查询域名相关记录。
- 递归解析器 通常代表客户端完成查询,并利用根、顶级域和权威 DNS 服务器逐步找到答案。
- A、AAAA、CNAME、MX、NS、TXT 等记录分别承担不同用途。
- TTL 控制 DNS 记录缓存时间,不是网站的访问时限,也不是 HTTP 缓存。
- DNS 既可使用 UDP,也可使用 TCP;DoT、DoH 则提供不同的加密传输方式。
- Java 的
InetAddress可以用于名称解析,但不能代替完整的 DNS 抓包与网络排障。
下一篇预告:《【计算机网络】第 9 篇:从输入网址到网页显示,中间到底发生了什么?》我们会把 DNS、TCP、TLS、HTTP 串联起来,完整梳理一次 Web 访问流程。
我是程序员大海,下期我们不见不散.
参考资料
- RFC 1034:Domain Names — Concepts and Facilities
- RFC 1035:Domain Names — Implementation and Specification
- RFC 7766:DNS Transport over TCP — Implementation Requirements
- RFC 7858:Specification for DNS over Transport Layer Security (TLS)
- RFC 8484:DNS Queries over HTTPS (DoH)
- Java InetAddress 官方文档
本文中的域名与地址示例用于讲解,不代表真实网站的当前 DNS 记录;未声称在某台机器上执行过命令或获得特定运行结果。
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/2401_86617027/article/details/169164475




