一家服务商的 DNS 管理 API 已经返回成功,某地区用户仍解析到旧地址。排查时需要沿控制面发布、权威副本、递归缓存、应用缓存逐层核对,而不是只检查管理页面。DNS 的分布式机制提高扩展性,也让“变更已提交”和“用户已切换”之间存在多个可观察阶段。
| 工作对象 | 负责什么 | 主要观察点 |
| 注册/委派管理 | 父区 NS、glue、DS 等 | 父区实际发布的状态 |
| 权威服务 | 提供所管理 zone 的数据 | 各权威实例、SOA、签名和应答 |
| 递归服务 | 查询、验证、缓存与策略 | 命中率、上游失败、验证和尾延迟 |
| 本机/应用解析 | 选择上游、视图及本地缓存 | 应用真实路径、VPN/浏览器设置 |
| DNS 流量调度 | 按策略生成答案 | 缓存粒度、健康检查与应用连接分布 |
根服务:13 个名字,不是 13 台物理机
根区配置了从 a 到 m 的 13 个具名权威服务,由各运营者部署众多实例。实例数和站点持续变化,不适合把一个无日期的数量写成架构常量。root hints 提供根服务名称和地址,帮助递归器启动;它不是完整根区,也不是 DNSSEC 信任锚。IANA:根名称服务器
根区包含顶级域委派、相应地址及 DNSSEC 等数据,根提示文件只用于找到根服务器,不等于完整根区。需要大小时应对明确版本/格式实际测量,不把提示文件大小当完整区规模。IANA:根区与文件
根服务器不提供普通递归服务,但可以对根区自身负责的数据或相应不存在情况作答,不是只会 referral;收到 RD=1 也不意味着它必须替请求者递归。递归器通过 priming 获得根 NS 等当前信息,启动信息陈旧与根区信任链错误是两类问题。RFC 8109:根启动查询
Anycast:路由选择不等于地理距离排序
多个位置宣告同一服务前缀,网络根据可达性、路由策略及各项度量选择路径。AS_PATH 只是 BGP 候选因素之一,LOCAL_PREF 等可能更早决定结果;所谓“最近”不能直接等于最少 AS 数、最短公里数或最低 RTT。RFC 4786:Anycast 运维
从一个观察点访问同一 IP,可能随路由变化切到另一实例。多个实例一致宣告同一 /24 并不能保证永久会话粘性;恰恰因为同一前缀多地宣告,选择才依赖上游路由状态。
短 UDP 查询较容易重试,但 DNS 还使用 TCP、TLS、HTTPS、QUIC 等持有连接状态的承载。路径突然切换时,新实例可能没有旧连接状态,需要合适的路由稳定性、状态处理或重连策略。不能笼统说“DNS 每次独立,所以 Anycast 完美没有代价”。
服务故障也未必导致链路或 BGP 会话故障。若实例无法正确回答却仍宣告路由,流量可能持续落入黑洞;健康检测与撤路由的联动、撤回时机和覆盖前缀需要设计。另一方面,频繁撤回会造成抖动,不应让每次短暂超时直接触发全站撤路由。
权威冗余:多个 NS 名字不等于独立故障域
两个 NS 若共用同一机房、上游、账户或发布流水线,仍可能一起失效。设计需要考虑服务和管理面的共同依赖,并确保每个宣告权威都能正确回答所需数据。
primary/secondary 可以通过 AXFR/IXFR 等同步,托管服务也可用内部数据库发布;无论采用什么机制,都应观察各权威实际结果。SOA serial 有助于检查某些部署的版本,但签名有效性、记录内容与全节点加载结果也要核对。
对外权威通常不应同时向任何人开放递归。BIND 的 views、访问控制与递归选项可以表达不同策略,但其匹配顺序和具体语义要按所用版本核对;“监听了 53”并不说明角色隔离正确。BIND 配置参考
递归容量:缓存命中率决定上游压力
假设服务收到 10000 查询/s,90% 在所讨论的缓存层命中,则约 1000 查询/s 需要进一步处理。若每个未命中平均触发 3 次上游事务,平均上游负载约 3000 次/s;命中率降到 50% 后可升至 15000 次/s。这里的“3”是示例测量假设,实际别名、委派缓存、DNSSEC 和失败重试会改变它。
平均上游事务 3000/s、平均在途时间 20 ms,则按稳定系统的 Little 定律,在途量均值约 60。它不能作为连接池或内存的唯一容量,因为冷启动、权威超时和重试尾部可能远大于均值。
| 指标 | 帮助区分 |
| 命中/未命中与请求类型 | 容量变化是否来自缓存或工作负载 |
| 上游事务数、重试和超时 | 外部权威问题还是本地处理问题 |
| RCODE 与验证失败原因 | NXDOMAIN、SERVFAIL、DNSSEC 错误分别来自哪里 |
| p50/p95/p99 与请求阶段 | 平均正常但尾延迟严重的路径 |
| TCP 回退与响应大小 | EDNS、分片、DNSSEC 大包相关问题 |
重启多个递归实例会同时丢失热缓存,可能放大上游压力。负缓存、请求合并、预取和 serve-stale 各有用途与正确性边界,不能只追求把命中率数字做到最大。
命中率少十个百分点,上游会多忙多少?
保持每次未命中的工作量不变,把命中率从90%降到50%,上游从3000变为15000次/s,是五倍而非“只多40%”。随后只拉长时延,上游速率不变,在途量继续增加,这正是 Little 定律中两个因子的分工。
λu=λq(1−h)k,Lu=λuWu
正在呈现知识画面
命中率少十个百分点,上游会多忙多少?缓存命中率先改变上游到达率,延迟再决定平均占用。相同查询吞吐下,慢上游可以显著增加在途事务。
{"id":"dns-cache-upstream-load","title":"命中率少十个百分点,上游会多忙多少?","summary":"缓存命中率先改变上游到达率,延迟再决定平均占用。相同查询吞吐下,慢上游可以显著增加在途事务。","height":1000,"html":"<h2 data-i18n=\"heading\"></h2><p class=\"intro\" data-i18n=\"intro\"></p><div class=\"control\"><label for=\"hit\" data-i18n=\"hit\"></label><output for=\"hit\" id=\"hit-value\"></output><input id=\"hit\" type=\"range\" min=\"0\" max=\"100\" value=\"90\" step=\"1\"></div><div class=\"control\"><label for=\"fan\" data-i18n=\"fan\"></label><output for=\"fan\" id=\"fan-value\"></output><input id=\"fan\" type=\"range\" min=\"1\" max=\"6\" value=\"3\" step=\"1\"></div><div class=\"control\"><label for=\"latency\" data-i18n=\"latency\"></label><output for=\"latency\" id=\"latency-value\"></output><input id=\"latency\" type=\"range\" min=\"1\" max=\"1000\" value=\"20\" step=\"1\"></div><div id=\"flow\" class=\"budget\"></div><div class=\"metrics\"><div><span data-i18n=\"rate\"></span><strong id=\"rate\"></strong></div><div><span data-i18n=\"inflight\"></span><strong id=\"inflight\"></strong></div></div><p id=\"equation\" class=\"formula\"></p><details class=\"scope\"><summary data-i18n=\"scopeLabel\"></summary><p data-i18n=\"scope\"></p></details>","css":".intro{margin:8px 0 18px;color:var(--muted);font-size:14px}.caption,.hint{font-size:12px;color:var(--muted);margin-top:12px}.control{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:6px 12px;align-items:center;margin:14px 0;font-size:13px}.control label{font-size:13px}.control output{color:var(--accent);min-width:5em;text-align:right;font-variant-numeric:tabular-nums}.control input{grid-column:1/-1;width:100%;margin:0}.presets{display:flex;gap:4px;align-items:stretch}.presets button{flex:1 1 0;min-width:0;overflow-wrap:anywhere;font-size:13px}.actions{display:flex;gap:8px;flex-wrap:wrap;margin:14px 0}.actions button{flex:1;min-width:0;font-size:13px;min-height:42px}.copy{display:grid;font-size:14px;margin:16px 0}.copy>*{grid-area:1/1;margin:0}.reserve{visibility:hidden}.scope{margin-top:14px;color:var(--muted);font-size:12px}.scope summary{padding:8px 0;cursor:pointer}.scope p{margin-top:10px}.two{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin:16px 0}.card{border:1px solid var(--rule);border-radius:9px;padding:14px;min-width:0}.card header{font-size:14px;font-weight:600;margin-bottom:10px}.card button{font-size:12px;width:100%;min-width:0}.card small{display:block;font-size:12px;color:var(--muted)}.card code{font-size:12px;overflow-wrap:anywhere}.metrics{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin:16px 0}.metrics>div{border-left:2px solid var(--accent);padding-left:10px;min-width:0}.metrics span{display:block;min-height:3.2em;color:var(--muted);font-size:12px}.metrics strong{font-size:23px;display:block;font-weight:500;overflow-wrap:anywhere;font-variant-numeric:tabular-nums}.formula{border-top:1px solid var(--rule);padding-top:12px;margin-top:14px;font-size:13px;font-variant-numeric:tabular-nums;overflow-wrap:anywhere}.value{font:500 20px var(--viz-font-ui)}.legend{display:flex;flex-wrap:wrap;gap:6px 14px;font-size:12px;color:var(--muted);margin:12px 0}.legend span:before{content:'';display:inline-block;width:8px;height:8px;border-radius:2px;background:var(--accent);margin-right:6px}.legend .second:before{background:var(--second)}.check{display:flex;align-items:center;gap:8px;font-size:13px;margin:12px 0}.check input{width:16px;height:16px;flex-shrink:0;accent-color:var(--accent)}select,input[type=text],input[type=number]{background:var(--paper);color:var(--ink);font:inherit;font-size:13px;padding:10px;border:1px solid var(--rule);border-radius:7px;max-width:100%;min-width:0}select{width:100%;min-height:42px}.band{height:20px;display:flex;background:var(--surface);border-radius:4px;overflow:hidden}.band i{height:100%;display:block;background:var(--accent);transition:width .25s}.band i.second{background:var(--second)}button:disabled{cursor:default}.status{font-size:13px;min-height:4.8em}.mono{font-family:var(--viz-font-mono);font-variant-numeric:tabular-nums}.muted{color:var(--muted)}\n@media(max-width:480px){.two{gap:8px}.card{padding:12px 9px}.actions button,.presets button{font-size:12px}.metrics strong{font-size:20px}.metrics{gap:8px}}\n@media(prefers-reduced-motion:reduce){*,*::before,*::after{transition:none!important;animation:none!important}}\n.track-row{margin:16px 0}.track-row>span{display:block;font-size:12px;color:var(--muted);margin-bottom:7px}.track{display:flex;gap:5px;min-width:0}.cell{flex:1;min-width:0;min-height:48px;border:1px solid var(--rule);border-radius:5px;background:var(--surface);display:flex;align-items:center;justify-content:center;text-align:center;padding:5px 3px;font-size:12px;overflow-wrap:anywhere;font-variant-numeric:tabular-nums}.cell.on{background:var(--accent-soft);border-color:var(--accent)}.cell.gold{background:var(--second-soft);border-color:var(--second)}.cell.empty{border-style:dashed;color:var(--muted)}.cell.error{border-color:var(--second);text-decoration:line-through}.choices{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px;margin:14px 0}.choices button{min-width:0;padding:10px 4px;font-size:12px;overflow-wrap:anywhere}.choices button[aria-current=true]{border-color:var(--accent);background:var(--accent-soft)}.relation{display:grid;grid-template-columns:minmax(0,1fr) 28px minmax(0,1fr);align-items:center;gap:6px;margin:12px 0}.relation .cell{min-height:72px}.relation>i{text-align:center;font-style:normal;color:var(--accent)}.readout{font-size:13px;white-space:pre-line;min-height:6.4em;overflow-wrap:anywhere}.plot{position:relative;border-left:1px solid var(--rule);border-bottom:1px solid var(--rule);padding:8px 0;margin:18px 0}.plot-row{height:28px;position:relative;margin:4px 0;background:var(--surface)}.plot-row i{position:absolute;inset-block:5px;background:var(--accent);min-width:2px;transition:width .2s,left .2s}.plot-row b{position:relative;padding:4px 6px;font:11px/28px var(--viz-font-ui);background:var(--paper);border-radius:3px}.axis{display:flex;justify-content:space-between;font-size:11px;color:var(--muted)}\n\n/* Action labels must remain readable across locales and narrow embeds. */\n.actions{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}\n.actions button{overflow-wrap:anywhere;white-space:normal;min-height:58px;padding:8px}\nbutton{overflow-wrap:anywhere}\n@media(min-width:640px){.actions{grid-template-columns:repeat(3,minmax(0,1fr))}}\n\n.metrics span{overflow-wrap:anywhere}\n.panel{border:1px solid var(--rule);border-radius:9px;padding:12px;margin:14px 0;min-width:0}.panel h3{font-size:13px;margin:0 0 10px;color:var(--muted)}.source{font:13px/1.8 var(--viz-font-mono);white-space:pre-wrap;overflow-wrap:anywhere;margin:12px 0}.source mark{background:var(--accent-soft);color:var(--ink);border-bottom:2px solid var(--accent)}.source .fault{background:var(--second-soft);border-color:var(--second)}.diagram{display:block;width:100%;height:auto;max-height:320px;margin:14px 0;overflow:visible}.diagram text{fill:var(--ink);font:12px var(--viz-font-ui)}.diagram .edge{stroke:var(--muted);stroke-width:1.5;fill:none}.diagram .edge.on{stroke:var(--accent);stroke-width:3}.diagram .node{fill:var(--surface);stroke:var(--rule);stroke-width:1.5}.diagram .node.on{fill:var(--accent-soft);stroke:var(--accent)}.diagram .node.gold{fill:var(--second-soft);stroke:var(--second)}.log{font:12px/1.8 var(--viz-font-mono);white-space:pre-line;overflow-wrap:anywhere;min-height:7.2em}.table{display:grid;gap:5px;margin:14px 0}.table .tr{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:5px}.table .tr>*{padding:8px 5px;background:var(--surface);border-radius:4px;min-width:0;overflow-wrap:anywhere;font-size:12px}.table .tr .on{background:var(--accent-soft)}.table .tr .gold{background:var(--second-soft)}.choices button{min-height:44px}.metrics strong{min-height:1.6em}.code-line{display:block}.code-line.on{background:var(--accent-soft);border-left:2px solid var(--accent);padding-left:6px}.status-badge{font-size:12px;color:var(--accent)}.tile-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px}.tile-grid .cell{min-height:40px}.actions button{min-height:48px}.form-field{display:grid;gap:8px;margin:14px 0;font-size:13px}.form-field input{width:100%;font-family:var(--viz-font-ui)}.metrics.three{grid-template-columns:repeat(3,minmax(0,1fr))}.formula{min-height:3.2em}.presets{flex-wrap:wrap}.presets button{flex-basis:25%;min-height:44px}\n\n.budget{display:flex;height:28px;margin:16px 0;background:var(--surface);border-radius:5px;overflow:hidden}.budget i{display:block;background:var(--accent);transition:width .2s}.budget i.gold{background:var(--second)}.intervals{margin:16px 0}.interval{position:relative;height:36px;background:var(--surface);margin:6px 0;border-radius:4px;overflow:hidden}.interval i{position:absolute;height:100%;background:var(--accent-soft);border-left:2px solid var(--accent)}.interval i.gold{background:var(--second-soft);border-color:var(--second)}.interval span{position:relative;z-index:1;font:12px/36px var(--viz-font-ui);padding-left:7px}.table .tr>*{min-height:4.8em}.formula{white-space:pre-line;min-height:7.2em}.actions:has(>button:only-child){grid-template-columns:1fr}.metrics strong{min-height:3.2em}.rangegrid{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:3px;margin:14px 0}.rangegrid .cell{min-height:30px;padding:3px 1px;font-size:10px}.message{min-height:7.2em;white-space:pre-line;font:13px/1.8 var(--viz-font-ui);overflow-wrap:anywhere}\n/* Allow CJK hanging punctuation without overflowing a metric's border box. */\n.metrics>div{padding-right:4px}.metrics span{line-break:anywhere}\n\n","js":"const $=s=>document.querySelector(s);const set=(id,v)=>$('#'+id).textContent=v;const t=k=>viz.t(k);function cells(id,values){$('#'+id).replaceChildren(...values.map(v=>{const e=document.createElement('div');e.className='cell '+(v.cls||'');e.textContent=v.text;e.title=v.title||v.text;return e;}));}function pressed(mode){document.querySelectorAll('[data-mode]').forEach(e=>e.setAttribute('aria-pressed',String(e.dataset.mode===mode)));}const esc=s=>String(s).replace(/[&<>\"']/g,c=>({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));const fmt=s=>'{'+[...s].sort().join(', ')+'}';function graph(id,nodes,edges){const el=$('#'+id);el.setAttribute('viewBox','0 0 360 200');el.innerHTML='<defs><marker id=\"arrow-'+id+'\" viewBox=\"0 0 10 10\" refX=\"8\" refY=\"5\" markerWidth=\"5\" markerHeight=\"5\" orient=\"auto-start-reverse\"><path d=\"M 0 0 L 10 5 L 0 10 z\" fill=\"var(--muted)\"/></marker></defs>'+edges.map(e=>{const a=nodes[e[0]],b=nodes[e[1]],dx=b.x-a.x,dy=b.y-a.y,d=Math.hypot(dx,dy)||1;if(edges.some(r=>r[0]===e[1]&&r[1]===e[0])){const nx=-dy/d,ny=dx/d;return '<path class=\"edge '+(e[2]?'on':'')+'\" d=\"M '+(a.x+dx/d*22+nx*12)+' '+(a.y+dy/d*22+ny*12)+' Q '+((a.x+b.x)/2+nx*38)+' '+((a.y+b.y)/2+ny*38)+' '+(b.x-dx/d*25+nx*12)+' '+(b.y-dy/d*25+ny*12)+'\" marker-end=\"url(#arrow-'+id+')\"/>';}return '<line class=\"edge '+(e[2]?'on':'')+'\" x1=\"'+(a.x+dx/d*25)+'\" y1=\"'+(a.y+dy/d*25)+'\" x2=\"'+(b.x-dx/d*28)+'\" y2=\"'+(b.y-dy/d*28)+'\" marker-end=\"url(#arrow-'+id+')\"/>';}).join('')+nodes.map(n=>'<g><circle class=\"node '+(n.cls||'')+'\" cx=\"'+n.x+'\" cy=\"'+n.y+'\" r=\"25\"/><text x=\"'+n.x+'\" y=\"'+(n.y+4)+'\" text-anchor=\"middle\">'+esc(n.name)+'</text>'+(n.sub?'<text x=\"'+n.x+'\" y=\"'+(n.y+43)+'\" text-anchor=\"middle\">'+esc(n.sub)+'</text>':'')+'</g>').join('');}function table(id,rows){$('#'+id).classList.add('table');$('#'+id).replaceChildren(...rows.map(r=>{const row=document.createElement('div');row.className='tr';r.forEach(x=>{const c=document.createElement('div');if(typeof x==='object'){c.textContent=x.text;c.className=x.cls||'';}else c.textContent=x;row.append(c)});return row;}));}function band(id,parts,total){$('#'+id).replaceChildren(...parts.map((p,i)=>{const e=document.createElement('i');e.style.width=(100*p.value/total)+'%';e.className=i%2?'gold':'on';e.title=p.name+': '+p.value;return e}));}function intervals(id,items,total){$('#'+id).replaceChildren(...items.map(p=>{const row=document.createElement('div');row.className='interval';const bar=document.createElement('i');bar.style.left=(100*p.start/total)+'%';bar.style.width=(100*(p.end-p.start)/total)+'%';bar.className=p.cls||'';const label=document.createElement('span');label.textContent=p.label;row.append(bar,label);return row;}));}function draw(){const h=+$('#hit').value,k=+$('#fan').value,w=+$('#latency').value,rate=10000*(1-h/100)*k;for(const id of ['hit','fan','latency'])set(id+'-value',$('#'+id).value);band('flow',[{name:'hit',value:h},{name:'miss',value:100-h}],100);set('rate',Math.round(rate));set('inflight',(rate*w/1000).toFixed(1));set('equation','λ = 10000×(1−'+h+'/100)×'+k+' = '+Math.round(rate)+' /s\\nL = λW = '+Math.round(rate)+'×'+w+'/1000 = '+(rate*w/1000).toFixed(1));$('#rate').dataset.value=rate;$('#inflight').dataset.value=rate*w/1000;}document.querySelectorAll('input').forEach(e=>e.oninput=draw);draw();","audio":false,"strings":{"fan":"每次未命中的上游事务数","heading":"命中率少十个百分点,上游会多忙多少?","hit":"缓存命中率(%)","inflight":"平均在途事务","intro":"调整命中率、每次未命中的上游次数与平均时延,分开观察吞吐与在途量。","latency":"上游平均在途时间(ms)","rate":"上游事务/s","reset":"重置","scope":"客户端10000查询/s,稳定均值模型;每次未命中平均上游次数可调。忽略合并、预取、尾部超时与重试反馈,不能据均值直接定池容量。","scopeLabel":"模型范围与约定"}}
CDN 与 ECS:权威通常先看到递归器
普通客户端把查询交给递归器,CDN 权威看到的源 IP 通常属于递归器,不是终端本身。地理位置策略用地址库和运营数据作判断,延迟策略也可能使用历史测量或聚合估计,不能假设每条 DNS 查询都实时 ping 所有候选 edge。
ECS 允许解析器携带客户端子网信息,权威可据此细分答案,并使用 scope 等规则约束缓存复用。源前缀长度不是协议强制所有 IPv4 都 /24、IPv6 都 /56;暴露精度、服务支持和配置均会影响结果。RFC 7871:EDNS Client Subnet
假设原本一个名称/类型只需缓存一份答案,引入 100 个相关子网范围后,可能需要多份带范围的缓存条目,复用率下降。ECS 不是只增加“更准的地理定位”而无其他成本,它还改变隐私与缓存行为。
Route 53 的 latency routing 依据其延迟数据选择配置区域的资源,而不是保证请求者到每个具体应用端点的瞬时最小延迟;地理距离近也可能因网络互联更差而更慢。AWS:延迟路由
DNS 负载均衡:选择应答不等于调度每个请求
在一份 A RRset 中列两个 IP,只表达多个地址,并没有用于 weighted round-robin 的权重字段。托管服务的加权策略是在生成应答时按配置选择记录或记录组;客户端如何使用多地址、连接是否复用及失败重试又是下一层行为。AWS:加权路由
例如解析器 R1 缓存到 A 后带来 10000 个业务请求,R2 缓存到 B 后仅带来 100 个。即使这两次 DNS 选择按数量是 1:1,应用负载却约 100:1。因此 DNS 权重不能保证字节量、连接数或交易数精确按比例分配。
健康检查失败后,新答案可避开故障端点,但旧缓存与已有长连接不会立即被“召回”。缩短 TTL 能改变未来缓存时窗,也会增加查询压力,且不能代替客户端重试、应用健康与连接迁移设计。
Split DNS:视图选择与上游路由都要明确
同一名称可在内部返回私有地址、外部返回公开地址,也可让特定后缀只交给内部 DNS。服务端 views 与客户端按后缀选择解析上游是不同实现位置,两者都需要明确哪类请求进入哪条策略。
例如 dashboard.example.com. 内部应答为 192.168.31.8,外部应答为文档示例公网地址。内部用户若浏览器独立 DoH 绕过系统分流,可能得到外部结果;VPN 断开后保留内部缓存也可能出现不可达。这不是 A 记录语法错误,而是查询路径和缓存上下文的问题。
缓存不能不加区分地把某视图结果提供给另一个视图。内外使用同一个受 DNSSEC 签名的名称空间时,还需设计内部授权与验证关系,不能让本地随意覆写与公共 DS 链互相冲突。
搜索域把短名称扩展为候选绝对名称,路由域则帮助选择上游;概念与具体实现语义需分别核对。配置了内部 DNS 也不代表全部应用都会使用它,应从应用实际路径验证。
发布一次变更:分阶段观察
修改普通记录,主要关注权威发布、签名及记录缓存;变更 NS 委派还需关注父区 NS/glue 与新旧权威服务重叠;更新 DS 又涉及 DNSSEC 父子区链及密钥缓存。三者不能用同一个“等待 TTL 就好”概括。
| 阶段 | 可核查证据 |
| 发布接受 | 控制面版本、配置校验与操作状态 |
| 权威可见 | 各 NS/实例实际返回的 RRset、SOA、签名 |
| 委派一致 | 父区 NS、必要 glue、DS 与子区状态 |
| 递归可见 | 多个独立解析路径的答案、TTL 与验证结果 |
| 应用可用 | 真正业务连接到哪一地址、是否完成预期请求 |
诊断可用 dig @<权威地址> <名称> A +norecurse 对照权威,再用所用递归器查询。dig +trace 展示工具自行迭代的路径,不等于应用配置的递归、DoH 或 VPN 路径;改变观察方式也改变了实验条件。本篇未运行真实外部探测。
本地容量与负载模型
query_rate = 10000
upstream_per_miss = 3
warm = query_rate*(1-.9)*upstream_per_miss
cold = query_rate*(1-.5)*upstream_per_miss
assert round(warm)==3000 and cold==15000
assert round(warm*.020)==60
requests = {'A':10000,'B':100}
assert requests['A']/requests['B']==100
assert 10000/(10000+100)>.99
print('缓存未命中负载、平均在途事务和 DNS/业务比例差异检查通过')
这些是明确假设下的算例,不是服务商性能实测;未修改根提示、公开委派、权威记录或解析器视图。
继续查阅