You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring框架项目中OkHttpClient随机抛出java.net.UnknownHostException问题

Spring项目中OkHttpClient随机出现UnknownHostException错误

在Spring框架项目中使用OkHttpClient发起请求时,随机抛出java.net.UnknownHostException: www.strava.com: Name or service not known错误。已设置1分钟连接超时,但请求失败时仅几秒就报错,相同请求有时成功有时失败。

相关代码如下:

String STRAVA_URL = "https://www.strava.com/";
String url = StravaConfig.STRAVA_URL + "/api/v3/oauth/token";

RequestBody requestBody = new FormBody
    .Builder()
    .add("client_id", StravaConfig.CLIENT_ID)
    .add("client_secret", StravaConfig.CLIENT_SECRET)
    .add("grant_type", "refresh_token")
    .add("refresh_token", account.getStravaRefreshToken())
    .build();

OkHttpClient client = new OkHttpClient.Builder()
        .connectTimeout(1, TimeUnit.MINUTES)
        .build();

Request request = new Request.Builder()
        .method("POST", requestBody)
        .url(url)
        .build();

Call call = client.newCall(request);
Response response = null;

try {
    response = call.execute();

    // 后续处理逻辑
} catch (Exception e) {
    // 此处抛出UnknownHostException
    e.printStackTrace();
    return e.toString();
}

问题原因

该问题源于Java默认的DNS解析机制:

  • Java会缓存DNS解析结果,包括解析失败的负缓存记录
  • 当系统配置多个DNS服务器时,Java不会自动进行故障转移,若第一个DNS服务器无法解析域名,直接抛出异常,不会尝试后续服务器
  • DNS解析的超时逻辑独立于OkHttpClient的连接超时设置,因此会快速报错

解决方案

方案1:调整JVM DNS缓存参数

通过JVM参数修改DNS缓存策略,缩短缓存有效期,让Java更快尝试其他DNS服务器:

  • -Dnetworkaddress.cache.ttl=60:设置DNS正缓存有效期为60秒(可根据实际需求调整)
  • -Dnetworkaddress.cache.negative.ttl=10:设置DNS负缓存(解析失败记录)有效期为10秒,避免长时间缓存失败结果

方案2:自定义OkHttpClient的DNS解析器

实现自定义DNS逻辑,手动处理多DNS服务器的故障转移:

OkHttpClient client = new OkHttpClient.Builder()
        .connectTimeout(1, TimeUnit.MINUTES)
        .dns(hostname -> {
            List<InetAddress> addresses = new ArrayList<>();
            // 配置多个DNS服务器地址
            String[] dnsServers = {"主DNS地址", "备用DNS地址"};
            
            for (String dnsServer : dnsServers) {
                try {
                    // 指定DNS服务器解析域名
                    InetAddress[] serverAddresses = InetAddress.getAllByName(hostname, InetAddress.getByName(dnsServer));
                    addresses.addAll(Arrays.asList(serverAddresses));
                    // 解析成功则跳出循环
                    break;
                } catch (UnknownHostException ignored) {
                    // 当前DNS解析失败,尝试下一个
                }
            }
            
            if (addresses.isEmpty()) {
                throw new UnknownHostException(hostname);
            }
            return addresses;
        })
        .build();

内容的提问来源于stack exchange,提问作者Matteo Battisti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 12:52:34