上周运营在群里炸锅:
"东南亚用户打开活动页要 7 秒,国内只要 1 秒,是不是 CDN 挂了?"
第一反应是 CDN 节点问题,结果 curl 一看,TLS 握手 30 ms,首包却 2.8 s ------典型的 DNS 拖后腿。
最后发现是新买的 .app
域名没开 EDNS0-Client-Subnet,权威 DNS 把新加坡用户解析到美国去了。
要根治,得先把 DNS 协议从"输入网址"到"拿到 IP"整条链路拆个透。
解决方案:把一次域名解析拆成 5 张"车票"

🔍 关键决策点
- 第 2 步没加 ECS,权威 DNS 只能按递归出口 IP(北京)返回最近节点,导致新加坡绕路。
- 第 8 步 CNAME 链太长,每多一跳就加一次 RTT。
原理剖析:三层报文结构,一层比一层"黑盒"
层级 | 协议字段 | 作用 | 常见坑 |
---|---|---|---|
传输层 | UDP 53 / TCP 53 | 0-RTT vs 可靠传输 | 截断后 fallback TCP 多一次 RTT |
应用层 | QR、Opcode、RD、RA、RCODE | 控制递归/权威行为 | RCODE=2 SERVFAIL 时浏览器会重试 3 次 |
扩展层 | EDNS0-Client-Subnet | 把用户真实网段带给权威 | 长度 > 512 字节时部分老旧防火墙直接丢包 |
抓包片段(tcpdump -nn -s0 -vvv port 53)
yaml
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 0x1234
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION: EDNS: version: 0, flags:; udp: 4096
;; CLIENT-SUBNET: 116.12.34.0/24/24
看到 CLIENT-SUBNET
就说明 ECS 生效,权威 DNS 能按用户真实地理位置返回最优 A 记录。
应用扩展:一条"秒开"配置模板
我们在 CDN 控制台 + 权威 DNS 做了三件事,把东南亚首包降到 300 ms:
bash
# 1. 权威 DNS 打开 ECS 支持(以 NS1 为例)
curl -X PUT https://api.nsone.net/v1/zones/xxx.com/api \
-d '{"edns_client_subnet":true}'
# 2. 缩短 CNAME 链
api.xxx.com 60 IN A 1.2.3.4 # 直接 A 记录,不再 CNAME 到 CDN 二级域名
# 3. 运营商递归 DNS 预热
dig @8.8.8.8 api.xxx.com # 上线前手动触发全球递归缓存
环境适配说明
- 国内用户走 114.114.114.114,海外走 8.8.8.8,两边 TTL 设 60 s,方便灰度回滚。
- 老旧安卓 4.x 不支持 ECS,需要单独在边缘节点做 GeoIP fallback。
对比主流"加速"方案
方案 | 原理 | 延迟收益 | 实施成本 |
---|---|---|---|
ECS | 把用户子网带给权威 | 100-300 ms | 改权威 DNS 配置 |
HTTPDNS | 绕过本地递归,直接 HTTP 拿结果 | 50-200 ms | 客户端集成 SDK |
DoH/DoT | 加密防劫持,复用 HTTP/2 多路复用 | 0-50 ms | 升级系统解析库 |
最终组合:
- 国内 App 内嵌 HTTPDNS 兜底;
- 海外浏览器走 DoH(Cloudflare 1.1.1.1);
- 权威 DNS 全量开 ECS。
举一反三:三个变体场景思路
-
灰度发布
在权威 DNS 把 10% 流量解析到新版本 IP,TTL 设 30 s,出问题 30 秒全局回滚。
-
多活容灾
利用 DNS 的
weighted
记录,主站 100 权重,灾备 0 权重;故障时一键把灾备调到 100,无需改 CDN。 -
防劫持
客户端预埋一份"可信 IP 列表",如果 DNS 返回的 A 记录不在列表里,立即切换到 DoH 重查,并上报异常。
小结
- DNS 不是"黑魔法",而是一张 5 跳的车票,每一跳都能量化。
- 打开 ECS、缩短 CNAME、预热递归缓存,是跨国业务的三板斧。
- 把 DNS 指标(解析耗时、TTL、ECS 命中率)接进 Prometheus,比"用户说慢"提前 5 分钟发现异常。