DNS 查询接口的能力边界:8 类记录、ANY 聚合与适用场景拆解
引入接口前先界定它能做什么、不能做什么很多开发者拿到一个 API 后的第一反应是“它能查什么”而忽略了一个更基础的问题这个接口在整体技术架构中处于什么位置它的能力边界在哪里。DNS 记录查询接口并非一台完整的 DNS 服务器也不是权威解析服务的替身。它的工作方式是接收一个域名和记录类型以请求方身份通过指定的多家国内 DoH 并发源获取解析记录再将多份结果合并、去重并做结构化整理后返回。换句话说接口提供的是一次“增量查询”而非“递归解析”的能力它更适合作为开发流程中的信息收集工具而不是作为线上 DNS 基础设施的一部分。理解这条边界后续的选型、限流设计、缓存策略和结果解读才不会走偏。适用场景哪些业务会真正用到它域名资产记录巡检如果你维护了一批域名需要定期确认它们的 A / AAAA / CNAME / MX / TXT / CAA / SOA 等记录是否存在、是否被意外修改可以用该接口批量获取并对比。多类型查询让一次请求覆盖多种业务需求比如同时检查 Web 服务的 A 记录、邮件系统的 MX 记录和证书签发相关的 CAA 记录。开发联调与故障排查在没有 dig 命令或网络受限的临时环境里通过 curl 向接口发一次请求就能确认某个域名的解析结果。配合 X-API-Key 和 type 参数也能快速验证 DNS 配置变更是否生效。上游数据源的交叉印证接口背后聚合了 AliDNS、DNSPod、360 三家 DoH 源并把命中同一记录的来源写入 sources 字段。当本地解析结果与预期不一致时可以通过该字段判断这是一条普遍生效的记录还是个别 DNS 服务器的特殊结果。CAA、MX、SOA 等结构化字段消费CAA、MX、SOA 这类记录在纯文本形式下难以直接处理。接口对它们做了拆分MX 拆成 priority 与 exchangeCAA 拆成 flags / tag / valueSOA 拆出 mname 等字段。这类解析结果特别适合直接写入配置巡检平台或证书管理工具。不适合用这个接口的场景高 QPS 的全量域名扫描该接口的限速为 10 QPS。如果要对数十万乃至百万级域名做全量遍历单个账号直接循环请求会迅速打满限额并造成超时。此类场景应当走自己的递归解析或批量任务队列而不是把该接口当成公共解析池。要求严格权威视角的场景由于接口对三个 DoH 源的数据做合并去重它反映的是“公共解析视角”企业内网私有域名、split-horizon DNS、按地理位置动态解析的场景均不在覆盖范围内。若要验证内网域名或本地路由直接用权威服务器查询更合适。需要完整历史记录或变更日志接口是即时查询会返回当前从 DoH 源能获取到的记录不提供历史变更轨迹。如果你需要审计“某个域名三个月前做过哪些改动”应自行搭建采集任务并存储历史数据。接口协议与参数边界项值说明接口路径GET https://v1.apizero.cn/api/dns-query仅支持 GET 请求限速10 QPS超过之后的行为以文档为准分类开发工具属于通用查询能力鉴权X-API-Key可选不携带则走匿名额度Query 参数参数必填类型说明host是string域名接口会自动剥离 http(s)://、路径与端口type否string记录类型默认 A支持名称A/AAAA/NS/CNAME/MX/TXT/CAA/SOA/ANY或数字编码1/2/5/6/15/16/28/257type 参数是接口灵活性的核心既兼容旧调用方式中的数字编码1A、15MX、257CAA也支持可读性更强的记录名。如果你的业务配置中心已经存储了数字编码无需额外做映射即可直接使用。Header 参数参数必填类型说明X-API-Key否stringAPI Key不传则使用匿名额度鉴权不是硬性前置条件但需要注意的是匿名额度与携带 Key 的额度在 QPS 上限上未必一致。具体数值以官方文档为准建议在企业内部统一存放 Key便于后续做调用量追踪。使用 curl 发起查询不携带 Key 的最简 A 记录查询curl -sS \ -X GET \ https://v1.apizero.cn/api/dns-query?hostexample.com这个请求会返回 example.com 的 A 记录。由于未填写 type按参数默认值走 A 查询。携带 API Key 查询 MX 记录curl -sS \ -X GET \ -H X-API-Key: $APIZERO_API_KEY \ https://v1.apizero.cn/api/dns-query?hosthosttypeMX使用前请先将$APIZERO_API_KEY与host替换成真实值。查询全部记录类型curl -sS \ -X GET \ -H X-API-Key: $APIZERO_API_KEY \ https://v1.apizero.cn/api/dns-query?hostexample.comtypeANYANY 的含义是单次请求尽可能多地返回该域名的 DNS 配置。需要说明的是ANY 响应仍以三家 DoH 源能取到的记录为上限若上游源未返回某一类型接口不会凭空补充。响应结构逐个拆解接口返回的是 JSON外层字段如下字段类型含义codenumber业务状态码0 表示成功msgstring状态描述request_idstring单次请求标识便于追踪日志dataobject查询结果主体data 对象字段字段说明host实际参与解析的域名input用户在接口入参中传入的原始值type查询的记录类型名称type_code查询的记录类型数字编码exec_ms接口执行耗时毫秒total返回的记录条数notes附加说明通常为 null具体以文档为准sources本次查询可用的 DoH 源名称列表如 alidns / china360 / dnspodrecords记录数组每个包含单条解析记录input 与 host 分开返回是一个重要设计当你传入https://example.com/path这类带协议和路径的字符串时host 是剥离后的真实域名input 保留原始值便于排查入参清洗是否生效。records 数组中的单条记录以 MX 记录为例{ data: 10 mx.maillb.baidu.com., name: baidu.com, parsed: { exchange: mx.maillb.baidu.com, priority: 10 }, sources: [alidns, china360, dnspod], ttl: 600, type: MX, type_code: 15 }字段解读data是原始 RDATA 文本MX 记录就是“优先级 邮件服务器”name是记录所属的域名parsed是结构化拆分结果MX 拆出 exchange 与 priorityCAA 拆出 flags / tag / valueSOA 拆出 mname、serial 等字段sources表示该记录被哪些 DoH 源返回并非权威来源标识ttl是记录的缓存时长单位秒type与type_code是记录类型名称与数字编码。注意sources 字段的语义是“该记录来源于这几个 DoH”它不能用来计算“记录被访问了多少次”也不代表记录的权威归属。ANY 聚合查询的正确打开方式ANY 类型解决的核心问题是“我记不清某个域名到底配了哪几类记录”。在交付一个域名前用一次 ANY 请求就能拿到其现有配置输出中会混有多种 type 的记录。使用 ANY 时有两点需要留意ANY 返回的是接口上游源在那一刻能收集到的集合不必追求字段上的绝对完整如果代码逻辑强依赖“某种类型一定出现在 ANY 结果里”建议改为显式指定对应 type 查询避免因上游差异导致误判。具体到某种资源记录在 ANY 模式下是否被过滤、是否合并请以该接口文档中的说明为准。常见错误与排查切入点由于错误响应示例未在本文素材中完整展开这里只列出通用排查思路具体错误码与 HTTP 状态对应关系以文档为准。请求返回非 200常见原因是域名参数为空、host 填入的不是合法域名或网络层无法连通接口。建议先确认请求地址中的 host 已正确 URL 编码再检查客户端到 v1.apizero.cn 的链路。code / msg 提示业务错误一般与参数校验相关例如 type 传入了不支持的取值。type 允许的名称仅限 A/AAAA/NS/CNAME/MX/TXT/CAA/SOA/ANY数字编码仅限 1/2/5/6/15/16/28/257。查询成功但 total 为 0表示当前域名在该类型下没有记录或三家 DoH 源均未返回结果。可先换一个知名域名做对照测试区分是接口问题还是域名本身没有对应记录。接口耗时突然升高接口本身要并发请求多个 DoH 源耗时受上游影响会浮动。如果连续请求触发限流也表现为耗时上升。发生时建议减少并发并观察是否超出 10 QPS 的限制。工程化落地注意事项调用端必须做 QPS 控制10 QPS 是接口明确的边界。若是多线程程序建议在发送端设置信号量或令牌桶把并发数限制在 10/秒以内而不是依赖服务端限流后的报错来被动降速。# 伪代码控制调用速率 import time from threading import Lock class RateLimiter: def __init__(self, qps10): self.interval 1.0 / qps self.lock Lock() self.next_time time.time() def acquire(self): with self.lock: now time.time() if now self.next_time: time.sleep(self.next_time - now) self.next_time time.time() self.interval实际生产环境中可以选择现成的限流库但核心逻辑一致把速率控制在 10 QPS 以内。善用 TTL 字段做缓存records 返回里已经带上了 TTL建议用这个值作为本地缓存的过期时间。例如 TTL 为 600 的记录缓存 10 分钟即可减少请求次数也就不用担心 QPS 被打满。调用前清洗 host虽然接口支持自动剥离协议、路径和端口调用方仍建议先做一层校验只把纯域名传给接口。自动化任务中解析用户输入时尤其重要可以避免把异常内容带入日志。关注 type 参数默认值带来的可读性问题不传 type 时默认查询 A 记录这在批量场景里容易造成误解你以为系统在拉 MX实际拉的是 A。建议在调用代码中显式写明 type 参数让日志和代码语义保持一致。不要把 sources 当作权威依据sources 描述的是记录来源不等于这条记录在公网上“一定正确”。遇到解析争议时仍应回到权威 DNS 或本地递归服务器做最终裁定。参考文档文档页https://apizero.cn/aidocs/dns-query原始文档https://apizero.cn/aidocs/dns-query/raw.md