用 dnspython 的 dns.resolver.resolve() 查 srv 记录最可靠,需指定完整服务名(如 _redis._tcp.db.example.com),结果中 r.target 是域名需二次解析,r.port 为整数,优先级越小越先尝试,权重仅同优先级内生效。

Python 里怎么查 DNS SRV 记录
直接用 dns.resolver(来自 dnspython)最稳,socket.getaddrinfo 不支持 SRV,别试。
常见错误是以为系统级 DNS 工具(比如 dig 或 nslookup)能被 Python 自动调用——它不能,得自己发查询。也有人误用 socket.getservbyname,那只是查本地 /etc/services,和 DNS SRV 完全无关。
- 装库:
pip install dnspython - 查记录时必须带完整服务名格式,比如
_http._tcp.example.com,漏下划线或协议会返回 NXDOMAIN - 默认走系统 DNS,如需指定服务器(比如测试用 CoreDNS),加
resolver.nameservers = ['127.0.0.1'] - 超时和重试要显式设,否则默认可能卡住几秒:
resolver.timeout = 2,resolver.lifetime = 3
import dns.resolver
try:
answers = dns.resolver.resolve('_redis._tcp.db.example.com', 'SRV')
for r in answers:
print(f'{r.target}:{r.port} (prio={r.priority}, weight={r.weight})')
except dns.resolver.NXDOMAIN:
print('域名不存在')
except dns.resolver.NoAnswer:
print('有响应但没 SRV 记录')
except dns.exception.Timeout:
print('DNS 查询超时')
SRV 记录字段怎么映射到 Python 对象
dnspython 返回的 SRV 类型记录对象字段名和 RFC 2782 一致,但容易看错权重和优先级的实际用途。
优先级(priority)不是“越高越好”,而是越小越先尝试;权重(weight)只在同优先级内生效,用于加权轮询——不是百分比,也不是并发数。
立即学习“Python免费学习笔记(深入)”;
51shop 由 PHP 语言开发, 使用快速的 MySQL 数据库保存数据 ,为中小型网站实现网上电子商务提供一个完美的解决方案.一、用户模块1. 用户注册:用户信息包括:用户ID、用户名、用户密码、性别、邮箱、省份、城市、 联系电话等信息,用户注册后不能立即使用,需由管理员激活账号,才可使用(此功能管理员可设置)2. 登录功能3. 资料修改:用户可修改除账号以后的所有资料4. 忘记密码:要求用
-
r.target是域名,不是 IP,得再查一次 A/AAAA 记录才能连 -
r.port是整数,可直接传给socket.connect()或requests的端口参数 - 如果
r.target是相对域名(比如srv1),会自动补上查询域,但生产环境建议全用绝对域名(末尾带点),避免解析歧义 - 不校验
target是否可达,也不做健康检查,这得你自己加逻辑
为什么服务发现时连不上目标地址
查到了 SRV 记录,但 connect() 失败,90% 是因为没做二次 DNS 查询——r.target 是个主机名,不是 IP。
另一个高频坑:容器或 Kubernetes 环境里,DNS 解析路径受 resolv.conf 影响,dnspython 默认不读它,得手动喂 nameserver;而 getaddrinfo 会读,但又不支持 SRV,形成断层。
- 别直接拿
r.target去socket.connect((r.target, r.port))—— 可能触发 IPv6 fallback 或超时 - 先用
dns.resolver.resolve(r.target, 'A')拿 IPv4,或同时查A和AAAA再选一个 - K8s 中若用 CoreDNS,确保
autopath插件没干扰 SRV 查询(某些版本会把_svc._tcp.ns.svc.cluster.local错改成_svc._tcp.ns.svc.cluster.local.svc.cluster.local) - 防火墙或 Service Mesh(如 Istio)可能拦截非标准端口,查 SRV 得到的
port不一定等于 Pod 实际暴露端口
要不要自己实现 SRV 负载均衡逻辑
别写。除非你真需要按权重做连接池、熔断、重试策略,否则用现成的客户端库更安全。
dnspython 只负责查,不排序、不去重、不缓存。自己实现排序容易忽略 RFC 规则:先按 priority 分组,每组内按 weight 随机抽样(不是简单加权平均),还要处理空响应和部分失败。
- 轻量场景直接遍历
answers,按priority升序 +weight抽样,连不通就下一个 - 高可用服务建议用
aiodns(异步)或封装进httpx/aiohttp的 mount 逻辑里,避免阻塞 - 缓存 SRV 结果必须设 TTL,
r.ttl来自 DNS 响应,别硬写 30 秒——有些服务设的是 5 秒,过期不更新就会连错实例 - 没有“刷新”机制,TTL 到了就得重新查,别指望后台自动轮询
SRV 本身不带健康状态,所有“自动剔除故障节点”的能力都得你额外加心跳或 TCP 探活,这点很容易被当成 DNS 层面的功能来期待。









