如何使用okhttp的DnsOverHttps包配置多DoH服务商并实现故障降级
多DoH服务商故障降级配置方案
实现思路
OkHttp 提供的 Dns 接口支持自定义扩展,我们只需要构造一个支持故障转移逻辑的自定义Dns实现,按优先级顺序持有多个DoH实例,解析时优先使用第一个实例,失败后自动尝试下一个即可。
步骤1:引入DoH依赖(如果未引入)
Gradle 配置示例:
implementation "com.squareup.okhttp3:okhttp-doh:4.12.0" // 可替换为最新稳定版
步骤2:分别构造优先级不同的DoH实例
先构造Cloudflare(优先使用)和Google(备用)两个DoH实例:
val appCache = Cache(File("cacheDir", "okhttpcache"), 10 * 1024 * 1024) // 公共的bootstrap客户端,可根据需要配置超时、代理等参数 val bootstrapClient = OkHttpClient.Builder() .cache(appCache) .connectTimeout(5, TimeUnit.SECONDS) .readTimeout(5, TimeUnit.SECONDS) .build() // 1. 优先使用的Cloudflare DoH val cloudflareDns = DnsOverHttps.Builder().client(bootstrapClient) .url("https://cloudflare-dns.com/dns-query".toHttpUrl()) .bootstrapDnsHosts(InetAddress.getByName("1.1.1.1"), InetAddress.getByName("1.0.0.1")) .build() // 2. 备用的Google DoH val googleDns = DnsOverHttps.Builder().client(bootstrapClient) .url("https://dns.google/dns-query".toHttpUrl()) .bootstrapDnsHosts(InetAddress.getByName("8.8.4.4"), InetAddress.getByName("8.8.8.8")) .build()
步骤3:实现带故障转移逻辑的自定义Dns
class FailoverDns(private val dnsList: List<Dns>) : Dns { override fun lookup(hostname: String): List<InetAddress> { var lastError: Exception? = null // 按顺序尝试所有DoH实例 for (dns in dnsList) { try { return dns.lookup(hostname) } catch (e: UnknownHostException) { lastError = e } } // 所有实例都失败时抛出异常 throw lastError ?: UnknownHostException("All DoH providers failed to resolve $hostname") } }
步骤4:配置到OkHttpClient
// 按优先级传入DoH实例列表,顺序越靠前优先级越高 val failoverDns = FailoverDns(listOf(cloudflareDns, googleDns)) val client = bootstrapClient.newBuilder() .dns(failoverDns) .build()
扩展说明
- 如果需要新增更多备用DoH服务商,只需要构造对应的
DnsOverHttps实例,添加到FailoverDns的构造列表即可 - 可以调整
bootstrapClient的超时时间,控制单个DoH解析失败的等待时长,优化故障转移的效率 - 也可以根据需要增加失败重试次数、故障冷却等逻辑,进一步优化
FailoverDns的实现
内容的提问来源于stack exchange,提问作者Sudhanshu Mishra
相关产品推荐
相关产品推荐

