Skip to content

DNS 域名解析 ​

#网络 · #DNS · #域名 · #CDN · #HTTPDNS · #CoreDNS

DNS(Domain Name System)是互联网的"电话簿"——将人类可读的域名转换为机器可路由的 IP 地址。从根域名服务器到本地缓存,从传统 UDP 查询到 HTTPDNS,DNS 的性能和安全性直接决定了用户体验。


DNS 解析流程 ​

mermaid
sequenceDiagram
    participant Browser as 浏览器
    participant Local as 本地 DNS 缓存
    participant Resolver as 递归解析器
    participant Root as 根域名服务器
    participant TLD as .com 顶级域
    participant Auth as 权威 DNS

    Browser->>Local: www.example.com 的 IP?
    Note over Local: hosts 文件 → 系统缓存 → 路由器缓存
    Local-->>Browser: 未命中

    Browser->>Resolver: 递归查询 www.example.com
    Resolver->>Root: www.example.com?
    Root-->>Resolver: .com 的 NS 地址

    Resolver->>TLD: www.example.com?
    TLD-->>Resolver: example.com 的 NS 地址

    Resolver->>Auth: www.example.com?
    Auth-->>Resolver: 1.2.3.4 (TTL=300)

    Resolver-->>Browser: 1.2.3.4
    Note over Browser: 缓存 TTL 秒

查询类型 ​

类型说明示例
递归查询客户端要求 DNS 服务器必须返回最终结果客户端 → 本地 DNS
迭代查询DNS 服务器返回"我不知道,但你可以问 xxx"本地 DNS → 根/顶级域

DNS 记录类型 ​

类型含义示例用途
AIPv4 地址www IN A 1.2.3.4域名 → IPv4
AAAAIPv6 地址www IN AAAA 2001:db8::1域名 → IPv6
CNAME别名/规范名www IN CNAME example.com域名别名
MX邮件服务器@ IN MX 10 mail.example.com邮件路由
NS域名服务器@ IN NS ns1.example.com指定权威 DNS
TXT文本记录@ IN TXT "v=spf1 ..."SPF/DKIM 验证
SRV服务定位_http._tcp IN SRV 0 5 80 www服务发现(如 K8s)
PTR反向解析4.3.2.1.in-addr.arpa IN PTR wwwIP → 域名
SOA授权起始包含主NS/管理员邮箱/序列号区域传输控制

DNS 解析性能 ​

延迟来源 ​

一次完整 DNS 解析(冷启动):
  根服务器: ~30-100ms(通常有缓存)
  顶级域:   ~20-50ms
  权威DNS:  ~10-30ms
  网络RTT:  ~5-50ms
  ─────────────────────
  总计:     ~50-200ms

缓存策略 ​

层级缓存位置TTL命中率
浏览器Chrome DNS 缓存1分钟高
操作系统/etc/hosts → systemd-resolvedTTL 决定很高
路由器家用路由器 DNS 缓存TTL中
ISP 递归解析器运营商 DNS (114.114.114.114)TTL极高
CDNDNS 调度层缓存较短 (30-120s)高

DNS 安全问题 ​

1. DNS 劫持 ​

正常:www.example.com → 1.2.3.4(真实 IP)
劫持:www.example.com → 5.6.7.8(恶意 IP)
劫持方式说明
本地 hosts 篡改恶意软件修改 /etc/hosts
路由器劫持修改路由器 DNS 设置
ISP 劫持运营商植入广告/统计页面
DNS 缓存投毒伪造 DNS 响应污染缓存

2. DNS 污染(GFW) ​

GFW 检测到敏感域名 → 向 DNS 请求方发送伪造响应(虚假IP)
→ 真正的响应到达时,客户端的查询端口已收到"回复"而丢弃

3. DNSSEC ​

通过数字签名验证 DNS 响应真实性:

DNS 记录 + RRSIG(数字签名)
         ↓ 验证
DNSKEY(区域公钥)← DS(父区域哈希)← 信任锚(根)

问题:部署率低(<30%),增加响应体积,不能防 DDoS。


DoT / DoH / DoQ ​

协议传输端口隐私防篡改性能
传统 DNSUDP/TCP 明文53❌❌最快
DoT (DNS over TLS)TCP + TLS853✅✅中
DoH (DNS over HTTPS)HTTP/2 + TLS443✅✅✅中
DoQ (DNS over QUIC)QUIC853✅✅快
DNSCrypt自定义加密协议自定义✅✅中

DoH 示例 ​

bash
# curl 使用 DoH 解析
curl --doh-url https://1.1.1.1/dns-query https://example.com

# 主流 DoH 服务商
# Cloudflare: https://1.1.1.1/dns-query
# Google:     https://dns.google/dns-query
# 阿里:       https://dns.alidns.com/dns-query
# DNSPod:     https://doh.pub/dns-query

HTTPDNS ​

传统 DNS 的问题 ​

  1. 域名劫持:运营商可能篡改
  2. 调度不准确:LDNS IP ≠ 用户 IP,CDN 调度偏差
  3. 解析延迟:递归链路长
  4. TTL 生效慢:中间缓存不遵守 TTL

HTTPDNS 原理 ​

客户端 → HTTP API → HTTPDNS 服务端 → 权威 DNS
                     ↑
                看到真实客户端 IP
                精准调度
                HTTPS 防劫持
GET /d?dn=www.example.com&ip=client_ip HTTP/1.1
Host: httpdns-api.aliyuncs.com

响应:
{
  "host": "www.example.com",
  "ips": ["1.2.3.4", "5.6.7.8"],
  "ttl": 120,
  "origin_ttl": 300
}

接入方式 ​

java
// Android OkHttp + HTTPDNS
OkHttpClient client = new OkHttpClient.Builder()
    .dns(new Dns() {
        @Override
        public List<InetAddress> lookup(String hostname) {
            // 优先 HTTPDNS
            List<String> ips = HttpDnsService.getIpsByHost(hostname);
            if (ips != null && !ips.isEmpty()) {
                return ips.stream().map(ip -> {
                    try { return InetAddress.getByName(ip); }
                    catch (Exception e) { return null; }
                }).collect(Collectors.toList());
            }
            // 降级到系统 DNS
            return Dns.SYSTEM.lookup(hostname);
        }
    })
    .build();

CDN 完整工作原理 ​

CDN DNS 调度 ​

用户 → 本地 DNS → CDN DNS 调度系统
                       ↓
                 根据 LDNS IP 判断用户位置
                       ↓
                 返回最近的边缘节点 IP
                       ↓
                 用户连接边缘节点

智能调度策略 ​

策略说明
GeoDNS根据 LDNS IP 地理库返回就近 IP
IP Anycast多个节点使用同一 IP,BGP 路由到最近
基于 RTT探测各节点延迟,返回最快的
基于负载返回负载最低的节点
分线路电信/联通/移动返回不同 IP

CDN 多级缓存架构 ​

CDN 并非只有一层缓存,而是分层回源以减少源站压力:

mermaid
flowchart TB
    User["用户"] --> Edge["L1: 边缘节点<br/>离用户最近"]
    Edge -->|"缓存未命中"| Parent["L2: 区域父节点<br/>覆盖一片地区"]
    Parent -->|"缓存未命中"| Origin["源站<br/>真正的服务器"]
    Edge -->|"命中"| User
    Parent -->|"命中"| Edge
层级节点数覆盖范围缓存命中率
L1 边缘节点数千城市/省份90-95%
L2 父节点数十全国/大区95-99%
源站1-3全球—

回源机制 ​

text
回源路径:
  用户请求 → 边缘节点 (miss) → 父节点 (miss) → 源站

控制回源的策略:
  1. 缓存 TTL (Time To Live): 根据文件类型设置
     - 图片/字体: 7-30 天
     - CSS/JS: 1-7 天(版本号控制更新)
     - HTML: 0-5 分钟(动态页面不缓存或短 TTL)

  2. 304 Not Modified: 协商缓存
     边缘节点携带 If-None-Match/If-Modified-Since 向源站验证
     源站返回 304 → 继续用缓存,不传输 body

  3. 缓存锁定 (Cache Lock):
     同一文件同时只有 1 个请求回源,其他排队等待
     → 防止"缓存击穿"导致大量并发回源

回源击穿防护 ​

text
问题场景: 一个热文件 cache 到期 → 边缘节点删除 → 数千用户同时请求
         → 数千请求同时回源 → 源站被打垮

Nginx proxy_cache_lock on: 同一资源同时只有 1 个请求回源
nginx
# Nginx 缓存锁配置
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:256m;
proxy_cache my_cache;
proxy_cache_lock on;               # 同一 key 只允许一个请求回源
proxy_cache_lock_timeout 5s;       # 等 5s 还没拿到也放行
proxy_cache_valid 200 1h;          # 200 缓存 1 小时

CDN 缓存刷新与预热 ​

操作用途生效时间
缓存刷新 (Purge)主动删除边缘节点旧缓存数秒-数分钟 (全网)
URL 刷新删除指定 URL 的缓存最快 ~几秒
目录刷新删除整个目录缓存数分钟
缓存预热 (Prefetch)提前加载热点文件到 CDN—
预热场景大促前预热商品图片/首页提前推送到边缘节点

CDN 与 HTTPS ​

text
CDN 部署 HTTPS 的两种模式:

方案 1: CDN 代持证书 (最常用)
  用户 ←→ CDN: HTTPS (CDN 持有域名证书)
  CDN ←→ 源站: HTTPS 或 HTTP

  优点: 用户就近完成 TLS 握手(低延迟)
  风险: CDN 能看到明文(需信任 CDN 厂商)

方案 2: 源站自有证书
  用户 ←→ CDN: HTTPS (CDN 代持)
  CDN ←→ 源站: HTTPS (源站证书,端到端加密)

  优点: CDN 看不到明文
  代价: 源站需承担 TLS 开销

CDN 常见问题排查 ​

现象可能原因诊断方法
部分地区访问慢该地区边缘节点异常多地区 ping/traceroute
缓存不生效TTL 设置错误、header 冲突检查 Cache-Control、Expires
回源率过高TTL 太短、缓存规则遗漏监控 CDN 回源流量
命中后内容不一致未刷新缓存对比 CDN 返回 vs 源站内容
HTTPS 证书错误证书过期/域名不匹配检查证书有效期和 SAN

调试工具 ​

bash
# A 记录查询
dig www.example.com A

# 跟踪解析链(迭代查询)
dig +trace www.example.com

# 指定 DNS 服务器
dig @8.8.8.8 www.example.com

# 反向解析
dig -x 1.2.3.4

# 查询 SOA(检查权威 DNS)
dig example.com SOA

# nslookup 简单查询
nslookup www.example.com

# 查看本地 DNS 缓存
# macOS: sudo dscacheutil -cachedump
# Linux: systemd-resolve --statistics

实战排查三步法 ​

DNS 问题是"网站打不开"的常见罪魁祸首,排查三步法:

bash
# 第 1 步:本地缓存正常吗?
nslookup www.example.com
# 如果超时 → DNS 服务器不可达(检查 /etc/resolv.conf)

# 第 2 步:权威 DNS 正常吗?
dig +short @ns1.example.com www.example.com
# 如果正常 → 是 LDNS 或运营商的问题
# 如果也失败 → 域名配置有问题

# 第 3 步:是否存在劫持?
dig +short @8.8.8.8 www.example.com  # Google DNS
dig +short @1.1.1.1 www.example.com  # Cloudflare DNS
dig +short @114.114.114.114 www.example.com  # 国内 DNS
# 如果权威返回的 IP 和 LDNS 不同 → 可能被劫持
# 如果国内外返回不同 IP → 正常(CDN 分地区调度)

DNS 安全 ​

DNS 最初设计于 1983 年,当时互联网规模很小、参与者都是信任的。它天生缺乏加密和认证——这意味着攻击者可以偷看(隐私泄漏)、篡改(DNS 劫持)甚至伪造(DNS 投毒)你的 DNS 请求。

方案原理隐私防篡改防劫持端口部署难度
DNSSEC对 DNS 记录签名,递归验证签名链❌(明文)✅❌(不防)53 UDP🟡
DoTDNS over TLS(公网标准端口 853)✅✅✅853 TCP🟢
DoHDNS over HTTPS(伪装成普通 HTTPS)✅✅✅✅✅443🟢
传统 UDP明文走 53 端口❌❌❌53 UDP—

关键认知:DNSSEC 只验证记录未被篡改,不加密。DoT/DoH 提供加密但需要信任 DNS 服务商。两者结合才是完整方案。

HTTPDNS — 绕过运营商 DNS ​

HTTPDNS 的核心思路是:不再通过运营商 LDNS,直接通过 HTTPS 向 DNS 服务商查询。运营商无法拦截 HTTPS 请求,因此无法劫持:

传统链路:
App → 运营商 LDNS (可能劫持/缓存不准) → 权威 DNS → 返回可能被篡改的 IP

HTTPDNS 链路:
App → HTTPS → HTTPDNS 服务商 (用客户端真实 IP 查) → 权威 DNS → 返回正确 IP

Go 实现思路:通过 net.Resolver 自定义 DNS 解析,用 HTTP API 查询代替系统 DNS:

go
// 使用自定义 Resolver 实现 HTTPDNS
resolver := &net.Resolver{
    PreferGo: true,
    Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
        // address 通常是 "8.8.8.8:53",这里替换为 HTTPDNS 逻辑
        d := net.Dialer{Timeout: 3 * time.Second}
        return d.DialContext(ctx, "tcp", "your-httpdns-api.com:443")
    },
}
// 配合 http.Client 使用
http.DefaultClient.Transport = &http.Transport{
    DialContext: resolver.DialContext,
}

CoreDNS 与 Kubernetes DNS ​

K8s DNS 架构 ​

在 Kubernetes 中,DNS 是服务发现的核心机制。CoreDNS 作为集群 DNS 服务器,为 Pod 提供 Service 名称解析:

mermaid
flowchart TB
    subgraph Pod["Pod (应用容器)"]
        App["应用进程"]
        Resolv["/etc/resolv.conf<br/>nameserver 10.96.0.10<br/>search default.svc.cluster.local"]
    end

    subgraph CoreDNS["CoreDNS (kube-system)"]
        CD1["CoreDNS Pod 1"]
        CD2["CoreDNS Pod 2"]
    end

    subgraph K8sAPI["Kubernetes API"]
        SVC["Service 对象"]
        EP["Endpoints 对象"]
    end

    App -->|"DNS 查询<br/>my-svc.default.svc.cluster.local"| CD1
    CD1 -->|"Watch"| K8sAPI
    CD1 -->|"返回 ClusterIP<br/>10.96.1.100"| App

    subgraph External["外部 DNS"]
        Upstream["上游 DNS<br/>(8.8.8.8)"]
    end
    CD1 -->|"非集群域名<br/>转发到上游"| Upstream

DNS 记录类型 ​

K8s 自动创建的 DNS 记录:

Service (ClusterIP):
  my-svc.default.svc.cluster.local → 10.96.1.100 (A 记录)

Service (Headless, clusterIP=None):
  my-svc.default.svc.cluster.local → Pod IP 列表 (A 记录)
  pod-name.my-svc.default.svc.cluster.local → 单个 Pod IP

StatefulSet Pod:
  web-0.nginx.default.svc.cluster.local → Pod IP (稳定 DNS 名)

SRV 记录:
  _http._tcp.my-svc.default.svc.cluster.local → 端口 + 目标

CoreDNS Corefile 配置 ​

.:53 {
    errors                          # 错误日志
    health {                        # 健康检查端点
        lameduck 5s
    }
    ready                           # 就绪探针

    kubernetes cluster.local in-addr.arpa ip6.arpa {  # K8s 插件
        pods insecure               # Pod DNS 记录
        fallthrough in-addr.arpa ip6.arpa
        ttl 30                      # TTL 30 秒
    }

    prometheus :9153                # 暴露 Prometheus 指标
    forward . /etc/resolv.conf      # 非集群域名转发到上游
    cache 30                        # 缓存 30 秒
    loop                            # 检测转发循环
    reload                          # 配置热加载
    loadbalance                     # DNS 轮询负载均衡
}

CoreDNS 性能调优 ​

问题现象解决
DNS 解析慢Pod 启动慢、请求超时增加 CoreDNS 副本数
DNS 5s 超时偶发 5s 延迟设置 ndots:2 减少搜索域
CoreDNS OOM大集群 Service 多增大内存限制
缓存命中率低频繁查询上游增大 cache TTL
yaml
# 优化 Pod 的 DNS 配置(减少无效查询)
apiVersion: v1
kind: Pod
spec:
  dnsConfig:
    options:
      - name: ndots
        value: "2"        # 默认 5,改为 2 减少搜索域尝试
      - name: single-request-reopen
        value: ""         # 避免 conntrack 竞争导致 5s 超时

DNS 性能基准数据 ​

DNS 查询延迟基准(典型值):

┌────────────────────────────────────────────────────┐
│ 场景                    │ 延迟        │ 说明        │
├─────────────────────────┼─────────────┼────────────┤
│ 本地 hosts 文件         │ < 0.1ms     │ 无网络开销  │
│ 系统 DNS 缓存命中       │ < 0.5ms     │ 内存查找    │
│ CoreDNS 缓存命中        │ 0.5-2ms     │ Pod→CoreDNS │
│ CoreDNS 缓存未命中      │ 2-10ms      │ 查 K8s API  │
│ ISP DNS 缓存命中        │ 1-5ms       │ 局域网 RTT  │
│ ISP DNS 递归解析        │ 20-100ms    │ 多跳查询    │
│ 跨国 DNS 解析           │ 100-300ms   │ 跨洋 RTT    │
│ HTTPDNS                 │ 10-50ms     │ HTTPS 开销  │
│ DoH (DNS over HTTPS)    │ 20-80ms     │ TLS 握手    │
└────────────────────────────────────────────────────┘

优化建议:
  - 本地缓存 > 集群缓存 > 递归解析
  - K8s 中设置合理的 ndots 避免无效查询
  - 高频域名预解析(DNS Prefetch)
  - 连接池复用避免重复解析

DNS 工程实践:客户端一次请求,常常先慢在解析阶段 ​

0. 一眼看懂:DNS 会怎样拖慢整个请求 ​

mermaid
flowchart LR
    A["本地缓存 / CoreDNS 未命中"] --> B["递归解析变慢"]
    B --> C["connect 更晚开始"]
    C --> D["TLS / 业务预算被压缩"]
    D --> E["timeout / retry / RT 抖动"]
场景优先看什么常见误判
connect 慢DNS 拆分耗时、缓存命中率一上来只怪网络
K8s 偶发 5sndots、CoreDNS、副本和上游 DNS只怪应用卡顿
外部依赖抖动resolver、DoH/HTTPDNS、降级路径只怪对方服务不稳
QPS 高时超时变多是否频繁重复解析、短连接多只怪服务容量不够

1. DNS 慢的危害,不只是多几十毫秒,而是直接吞掉整条请求预算 ​

在客户端视角里,一次 HTTP / RPC 请求经常先经历:

  • 域名解析
  • TCP connect
  • TLS 握手
  • 请求发送
  • 等待首包

所以如果 DNS 先慢了 50ms~200ms,后面的 connect、TLS、业务处理预算都会被压缩。

2. 很多“接口偶发超时”,根因其实不是服务端慢,而是解析链不稳定 ​

典型原因包括:

  • 本地 DNS / CoreDNS 缓存未命中
  • 上游递归解析器抖动
  • K8s ndots 导致多次无效搜索域查询
  • DoH / HTTPDNS 本身超时或降级路径有问题
  • 客户端没有复用连接,导致频繁重复解析

因此“服务端 RT 正常、客户端却超时”的问题,常常要先排除 DNS。

3. DNS 对客户端的影响,经常被误算成 connect 或请求耗时 ​

mermaid
flowchart LR
    A["DNS 解析慢"] --> B["connect 开始得更晚"]
    B --> C["TLS 握手预算被压缩"]
    C --> D["业务请求更容易超时"]
    D --> E["用户只看到接口慢 / timeout"]

所以如果监控里只看总请求时间、不拆 DNS / connect / TLS / TTFB,很容易误判慢点位置。

4. K8s / 容器环境里,DNS 抖动往往比单机环境更常见 ​

原因常见于:

  • ndots:5 带来多次搜索域尝试
  • CoreDNS 副本不足
  • CoreDNS 到上游 DNS 网络不稳
  • 大量短生命周期 Pod 带来缓存命中率下降

这也是为什么很多服务在本地正常、上集群后偶发多出 100ms~5s 抖动。

5. 客户端如果没有连接复用,会把 DNS 问题放大很多倍 ​

每次新建连接都可能触发:

  • 重新解析域名
  • 重新 connect
  • 重新 TLS 握手

因此短连接多的系统里,DNS 抖动会被放大成:

  • P99 RT 明显变差
  • 短时间大量超时
  • 某些外部依赖调用特别不稳定

6. 一个典型故障链:client -> dns -> upstream ​

mermaid
sequenceDiagram
    participant C as Client
    participant D as DNS Resolver/CoreDNS
    participant U as Upstream Service

    C->>D: 查询域名
    Note over D: 缓存未命中 / 上游递归抖动 / ndots放大
    D-->>C: 响应变慢
    C->>U: 开始 connect
    Note over C,U: connect/TLS 预算被压缩
    U-->>C: 最终请求超时或RT升高

7. 常见误判 ​

现象容易误判为实际可能是
connect 慢网络差DNS 先慢了
服务端日志很快监控错了客户端慢在解析和建连前置阶段
K8s 里偶发 5s应用卡顿ndots、CoreDNS、上游 DNS 超时
外部接口抖动对方服务不稳定本地 DNS / DoH / HTTPDNS 解析链不稳
QPS 一高就超时服务容量不够短连接过多导致重复解析和建连放大

8. 排障顺序 ​

现象优先看什么
请求总耗时高是否拆分 DNS / connect / TLS / TTFB
K8s 中偶发 5sndots、CoreDNS 指标、上游 DNS RT
外部依赖抖动本地 resolver、缓存命中率、DNS 降级路径
短连接系统超时多是否复用连接、是否频繁重复解析
跨地域请求慢递归解析路径、CDN 调度、DoH/HTTPDNS 策略

9. 一个实战原则 ​

text
先把 DNS 看成"请求入口阶段的第一跳延迟",
而不是一个独立的小模块;
只有这样,才能解释很多 connect 慢、TLS 慢、接口偶发超时的问题。

10. K8s 环境 DNS 故障专题 ​

10.1 ndots:5 — K8s DNS 放大的根源 ​

K8s 中 /etc/resolv.conf 默认配置 ndots:5,这是大量 DNS 问题的根因:

text
K8s Pod 默认 /etc/resolv.conf:
  nameserver 10.96.0.10         ← CoreDNS Service IP
  search default.svc.cluster.local svc.cluster.local cluster.local
  ndots:5

作用: 如果域名中 "." 的数量 < 5 → 先尝试拼接 search 域

实际效果:
  应用查询 "redis" (0 个点 < 5):
    → redis.default.svc.cluster.local   ← 第一次查询 (失败)
    → redis.svc.cluster.local           ← 第二次查询 (失败)
    → redis.cluster.local               ← 第三次查询 (失败)
    → redis                             ← 第四次查询 (成功)
    → 总共 4 次 DNS 查询!

  应用查询 "www.baidu.com" (2 个点 < 5):
    → www.baidu.com.default.svc.cluster.local  ← 第一次查询 (失败)
    → ... (同上)
    → 额外 3 次无用的 DNS 查询

影响量化:

text
场景: 一个请求需要 3 次外部 API 调用,每次触发 DNS 解析

ndots:5 → 每个 DNS 可能 4 次查询 = 3×4 = 12 次 DNS 查询
如果每次失败查询 5ms → 额外 45ms 延迟

P50: +5ms (缓存命中)
P99: +50-100ms (缓存未命中 + ndots 放大)

修复:

bash
# 方案1: 调低 ndots (推荐)
# Pod spec 中设置 dnsConfig:
dnsConfig:
  options:
    - name: ndots
      value: "1"          # 只对 0 个点的域名做 search 拼接

# 方案2: 用 FQDN (完全限定域名)
redis.default.svc.cluster.local.  # 末尾的 "." 阻止 search

# 方案3: 外部 API 用完整域名 + 本地缓存

10.2 DNS 递归查询完整时序 ​

mermaid
sequenceDiagram
    participant App as 应用
    participant Local as 本地 DNS 栈<br/>(glibc/nscd/systemd-resolved)
    participant CoreDNS as K8s CoreDNS
    participant Up as 上游 DNS<br/>(VPC / 公共 DNS)

    App->>Local: getaddrinfo("api.example.com")
    Local->>Local: 检查 /etc/hosts
    Local->>Local: 检查本地缓存

    alt 缓存命中
        Local-->>App: 直接返回
    else 缓存未命中
        Local->>CoreDNS: DNS 查询
        CoreDNS->>CoreDNS: 检查 CoreDNS cache

        alt CoreDNS 缓存命中
            CoreDNS-->>Local: 返回
        else 缓存未命中
            CoreDNS->>CoreDNS: 检查 CoreDNS hosts 插件
            CoreDNS->>Up: 递归查询
            Up-->>CoreDNS: A 记录
            CoreDNS->>CoreDNS: 写入缓存 (TTL)
            CoreDNS-->>Local: 返回
        end

        Local->>Local: 写入本地缓存
        Local-->>App: 返回
    end

10.3 DNS 缓存层级 ​

层级位置缓存策略排查命令
应用层JVM DNS cache / Go net.Resolver语言特定go: GODEBUG=netdns=1
glibcnscd (Name Service Cache Daemon)TTL 跟随 DNS 响应nscd -g
systemd-resolved系统 DNS stub resolverTTL 跟随resolvectl statistics
CoreDNSK8s 集群 DNSTTL + CoreDNS cache 插件CoreDNS metrics
上游 DNSVPC DNS / 公共 DNS (如 8.8.8.8)按 TTL通常不可控

10.4 Java vs Go DNS 缓存差异 ​

特性JavaGo
默认缓存✅ 有(networkaddress.cache.ttl)❌ 无内置缓存
默认 TTL30s(安全策略限制为 -1=永久)N/A
刷新策略固定 TTL 后重新解析每次解析走 OS
影响修改 DNS 后可能 30s 不生效每次查询走 OS resolver
调优-Dsun.net.inetaddr.ttl=5用 自定义 Resolver 加缓存
go
// Go 中给 DNS 加缓存
var resolver = &net.Resolver{
    PreferGo: true,
    Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
        d := net.Dialer{Timeout: 2 * time.Second}
        return d.DialContext(ctx, network, "10.96.0.10:53")
    },
}

// 可以用 github.com/mercari/go-dnscache 或自实现 TTL 缓存

批注模式

💬 文章评论

暂无评论,来说点什么吧 👇

编程学习笔记