ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Envoy 上游 DNS 解析架构详解:四种可插拔 DNS 解析器、配置参数与统计指标

Envoy 上游 DNS 解析架构详解:四种可插拔 DNS 解析器、配置参数与统计指标 Envoy 上游 DNS 解析架构详解四种可插拔 DNS 解析器、配置参数与统计指标【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoyEnvoy 中大量组件都依赖 DNS 解析STRICT_DNS / LOGICAL_DNS 集群、动态正向代理dynamic forward proxy系统、UDP DNS 过滤器等。本篇基于仓库架构文档 DNS Resolution 展开结合 DNS 解析器接口、工厂选择逻辑 和 c-ares 解析器配置 proto完整讲清 Envoy 的 DNS 解析是如何被抽象为可插拔扩展、四种内置解析器各自的行为差异、c-ares 解析器的全部配置参数及默认值以及dns.cares/dns.apple/dns.hickory统计树下的可观测指标。读完本文你可以准确选择解析器扩展、写出可复制的typed_dns_resolver_config并依据统计数据诊断解析失败、超时与通道重初始化等问题。一、谁在用 DNS 解析Envoy 中的 DNS 消费方根据架构文档Envoy 中有多类组件会发起 DNS 解析集群类型STRICT_DNS严格 DNS必须解析成功才加入 host与LOGICAL_DNS逻辑 DNS域名本身作为一个逻辑主机两种上游集群类型动态正向代理系统由集群与 HTTP 过滤器组合而成按请求目标域名动态建立上游连接其 DNS 缓存由typed_dns_resolver_config字段配置解析器可参考 HTTP 过滤器文档UDP DNS 过滤器作为 DNS 代理转发查询时也需要底层解析能力。这些消费方在源码中的落点可以相互印证集群侧在 cluster_factory_impl.cc 中根据集群类型构建解析器动态正向代理的 DNS 缓存在 dns_cache_impl.cc 中创建UDP 过滤器在 dns_filter.cc 中创建。所有消费方并不直接依赖某个具体解析库而是依赖统一的Network::DnsResolverFactory接口。二、可插拔抽象DnsResolver 接口与 DnsResolverFactory从源码结构看整个 DNS 子系统的抽象核心是两个接口文件DnsResolverFactory继承自Config::TypedFactory每个解析器扩展注册一个工厂其createDnsResolver(dispatcher, api, typed_dns_resolver_config)方法基于 typed 配置实例化具体解析器。dispatcher是本地工作线程的事件分发器api用于访问系统资源。DnsResolver异步解析器抽象核心方法有resolve(dns_name, dns_lookup_family, callback)发起异步解析返回ActiveDnsQuery*句柄调用方可用于取消查询resetNetworking()提示解析器重置网络状态典型场景是网络切换如 WiFi 切到蜂窝网络具体行为由各解析器自行决定可能涉及重建解析连接、重读解析目标等回调类型ResolveCb接收ResolutionStatusCompleted/Failure、details字符串以及解析出的地址/TTL 列表。值得注意的实现细节Completed并不代表“解析到地址”文档注释明确说明 NODATA、SERVFAIL、NONAME 等都属于“查询完成但无结果”的语义因此Completed才是更准确的表达。与解析结果相关的几个数据结构同样定义在 dns.hAddrInfoResponseA/AAAA 记录包含地址与 TTLSrvResponseSRV 记录包含 host、port、priority、weightDnsLookupFamily枚举V4Only、V6Only、Auto、V4Preferred、All控制 IP 版本查询策略ActiveDnsQuery::CancelReason区分QueryAbandoned调用方不再需要结果与Timeout调用方视角超时解析器可能借此销毁现有连接以便后续查询更快得到答案。三、四种内置 DNS 解析器扩展Envoy 通过可插拔扩展提供 DNS 解析默认使用 c-ares 作为解析库。仓库内置 4 个解析器扩展源码分别位于 source/extensions/network/dns_resolver/ 下的cares/、apple/、getaddrinfo/、hickory/子目录配置 proto 位于 api/envoy/extensions/network/dns_resolver/解析器扩展名类型配置消息适用平台/特点c-aresenvoy.network.dns_resolver.caresCaresDnsResolverConfig默认实现纯 C 异步 DNS 库Appleenvoy.network.dns_resolver.appleAppleDnsResolverConfig仅 iOS/macOS通过 Apple 专用 API 解析getaddrinfoenvoy.network.dns_resolver.getaddrinfoGetAddrInfoDnsResolverConfig基于系统getaddrinfo无解析器专属统计Hickory DNSenvoy.network.dns_resolver.hickoryHickoryDnsResolverConfig纯 Rust 解析器支持 DoT/DoH/DNSSEC3.1 c-ares默认c-ares 解析器实现位于 cares/dns_impl.h。从源码结构看它维护一个ares_channel所有调用与回调都假定发生在拥有创建用 dispatcher 的线程上resetNetworking()的实现就是reinitializeChannel()即重建 c-ares 通道。此外还包含以下机制均可在头文件成员变量中找到对应物UDP 通道周期刷新udp_channel_refresh_timer_配合max_udp_channel_duration定期重建通道避免陈旧 socket 状态并改善 UDP 端口负载分布双栈解析AddrInfoPendingResolution中dual_resolution_逻辑——当dns_lookup_family为V4Preferred或Auto时首次解析失败后发起第二次解析为All时则对两个 IP 族并发查询不可路由地址族过滤filter_unroutable_families开启时解析器会查询本机网络接口可用性若没有 IPv4 接口就不再返回 IPv4 地址。3.2 AppleiOS/macOSApple 解析器实现在 apple/apple_dns_impl.h仅当在 Apple 系统上构建时才编译。它可通过 runtime 特性envoy.restart_features.use_apple_api_for_dns_lookups在 Apple 系统上替代默认解析路径详见下文的工厂选择逻辑。3.3 getaddrinfo实现位于 getaddrinfo/getaddrinfo.cc直接委托系统的getaddrinfoAPI。架构文档特别指出getaddrinfo 解析器目前不产生解析器专属统计这是它与另外三种实现的可观测性差异监控时需注意。3.4 Hickory DNS纯 RustHickory 是一个基于 Hickory DNS 库的纯 Rust 解析器支持标准 DNSUDP/TCP、DNS-over-TLSDoT、DNS-over-HTTPSDoH与 DNSSEC 校验。从源码结构看hickory/hickory_dns_impl.h它通过 Envoy 的动态模块dynamic modules框架接入HickoryDnsResolverConfig保存的是一组从动态模块解析出来的函数指针on_dns_resolver_config_new_、on_dns_resolver_new_等而不是直接调用 Rust 代码。解析器在其自己的 Tokio runtime 线程上异步运行独立于 Envoy 的事件循环因此 DNS 解析不会阻塞 dispatcher 线程。四、解析器如何选择工厂选择优先级不同消费方集群、DNS 缓存、UDP 过滤器最终都通过 dns_factory_util.h 中的makeDnsResolverConfig()把各自异构的配置归一化为一个TypedExtensionConfig。从源码的分支顺序看选择优先级如下typed_dns_resolver_config显式指定配置中已存在 typed 解析器配置时原样采用优先级最高Apple 系统专用 APItryUseAppleApiForDnsLookups()检测平台与 runtime 特性envoy.restart_features.use_apple_api_for_dns_lookups满足则生成AppleDnsResolverConfigdns_resolution_config配置中存在该字段时将其resolvers与dns_resolver_options映射进CaresDnsResolverConfig遗留字段兜底handleLegacyDnsResolverData()为向后兼容复制旧字段如 bootstrap 与 DNS 缓存配置上的use_tcp_for_dns_lookups并始终生成 c-ares typed 配置。若完全未指定解析器配置则调用createDefaultDnsResolverFactory()从源码注释看默认行为是macOS 上用 Apple 解析器其他平台一律 c-ares。这一机制解释了架构文档中“默认使用 c-aresApple 系统额外提供 Apple API 路径”的描述。五、c-ares 解析器完整配置参数CaresDnsResolverConfig定义在 cares_dns_resolver.proto是内置 DNS typed 配置的典型示例。各字段说明如下字段类型说明resolversrepeated Address自定义 DNS 服务器地址列表是否覆盖系统默认由use_resolvers_as_fallback决定use_resolvers_as_fallbackbooltrue时仅当 c-ares 无法从系统如/etc/resolv.conf获得 nameserver 才使用resolvers否则resolvers覆盖系统默认。默认falsefilter_unroutable_familiesbool查询本机接口可用性过滤掉无对应网络接口地址族的解析结果如无 IPv4 接口则不返回 IPv4 地址dns_resolver_optionsDnsResolverOptions见下节udp_max_queriesUInt32Value限制基于 UDP 的 DNS 查询数量上限当前仅 c-ares 解析器适用query_timeout_secondsUInt64Value每个 name server 首次响应一个查询的超时秒数最小 1。注意c-ares 库默认 2 秒而Envoy 未设置时的默认值是 5 秒这是为维持既有行为而做的调整query_triesUInt32Value放弃前的最大查询尝试次数每次尝试可能使用不同 name server最小 1。c-ares 库默认 3 次Envoy 默认 4 次rotate_nameserversbool启用后对 name server 做轮转选择以均衡查询负载禁用默认时按配置顺序尝试。该设置覆盖系统的 name server 轮转配置edns0_max_payload_sizeUInt32Value最大 EDNS0 UDP 载荷字节数取值 512–4096。推荐值 1232安全默认避免分片或 4096最大允许不设置时由 c-ares 内部默认通常 1232max_udp_channel_durationDuration设置后 DNS 解析器会在该时长周期性地重新初始化 c-ares 通道帮助摆脱陈旧 socket 状态、改善 UDP 端口负载分布不设置则不做周期刷新reinit_channel_on_timeoutbooltrue时当查询以ARES_ETIMEOUT失败就重新初始化通道可快速恢复偶发的 UDP socket 不可用在网络抖动导致超时的环境中会增加通道重建频率此时更建议改用max_udp_channel_duration做周期刷新。默认falseqcache_max_ttlUInt32Valuec-ares 内部 DNS 响应缓存的最大 TTL秒取值 ≥ 0设为非零值时启用查询缓存并尊重响应 TTL不超过该上限。注意 c-ares 库默认缓存 1 小时而Envoy 该字段默认 0即完全禁用查询缓存5.1 DnsResolverOptionsdns_resolver_options指向 resolver.proto 中的DnsResolverOptions包含两个开关use_tcp_for_dns_lookups所有 DNS 查询使用 TCP 而非默认 UDPno_default_search_domain不使用默认搜索域仅按原样查询主机名或其别名。同一 proto 中的DnsResolutionConfigresolversdns_resolver_options则对应上文选择优先级中的第 3 级用于非 typed 的集群/DNS 缓存配置场景。六、统计指标dns.cares / dns.apple / dns.hickory三种解析器各自输出独立的统计树与源码中的统计宏定义一一对应如 cares/dns_impl.h 的ALL_CARES_DNS_RESOLVER_STATS。6.1 c-aresdns.cares统计树名称类型说明resolve_totalCounterDNS 查询总数pending_resolutionsGauge当前未完成的 DNS 查询数not_foundCounter返回NXDOMAIN或NODATA的查询数get_addr_failureCounterDNS 查询过程中的一般性失败数timeoutsCounter超时的查询数reinitsCounterc-ares 通道重新初始化次数其中reinits与timeouts组合特别有用若reinit_channel_on_timeout开启超时会触发通道重建reinits的持续增长可以帮助判断 UDP socket 健康问题。6.2 Appledns.apple统计树名称类型说明connection_failureCounter连接 DNS 服务器的失败尝试数get_addr_failureCounter调用 GetAddrInfo API 时的一般性失败数network_failureCounter因网络连通性导致的失败数processing_failureCounter处理来自 DNS 服务器数据时的失败数socket_failureCounter获取到 DNS 服务器的 socket 文件描述符的失败尝试数timeoutCounter超时的查询数6.3 Hickorydns.hickory统计树名称类型说明resolve_totalCounter已完成的 DNS 查询数pending_resolutionsGauge当前在途in-flight的 DNS 查询数not_foundCounter返回NXDOMAIN或NODATA响应的查询数get_addr_failureCounterDNS 查询过程中的一般性失败数timeoutsCounter超时的查询数6.4 getaddrinfogetaddrinfo 解析器目前不产生解析器专属统计架构文档 note 明确说明。若部署中使用该解析器需要依赖其他通用指标间接观察解析状况。七、实践要点小结不配置解析器时macOS 上默认 Apple 解析器可被 runtime 特性切换其他平台默认 c-ares需要精确控制时显式设置typed_dns_resolver_config它拥有最高优先级。超时与重试记住 Envoy 与 c-ares 库默认值不同超时 5s/4 次尝试而非库默认的 2s/3 次qcache_max_ttl默认 0 表示缓存禁用。UDP socket 健康周期性通道刷新max_udp_channel_duration与超时即重建reinit_channel_on_timeout二者取其一即可前者适合长期稳定运行后者适合偶发 socket 故障但会引入通道重建开销。可观测性按解析器选择对应的统计树dns.cares/dns.apple/dns.hickory使用 getaddrinfo 时没有专属指标可用。平台相关Apple 解析器仅在 iOS/macOS 构建中可用Hickory 通过动态模块框架以纯 Rust 运行在独立 Tokio 线程适合需要 DoT/DoH/DNSSEC 且希望解析不占用事件循环线程的场景。【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表