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
相关产品推荐
相关产品推荐

