其实在工作中有遇到过几种情况,一种是域名变更解析地址,但是生效时间是不定的,存在一定的延迟。
其次,每次的请求,都会走运营商 Local DNS,那么这时候有可能会被DNS劫持。
而且,运营商DNS解析有时候会影响到请求速度的,当运营商DNS解析慢的时候,软件也会受到一定的影响。
但是当客户端直接通过ip访问后就不会有这个问题了,阿里有个产品叫 HTTPDNS,可以解析出域名ip地址 。
首先在阿里云的控制台开通HTTPDNS,并且获得所需要的account id 。
并且在域名列表添加需要的域名,首次添加的域名,需要等一段时间才能生效。
以下以Android端为例子,话说我已经好久没碰Android了...
在 build.gradle中添加Maven仓库地址
allprojects {
repositories {
google()
jcenter()
maven {
url 'http://maven.aliyun.com/nexus/content/repositories/releases/'
}
}
}
在app.gradle 文件中添加依赖
dependencies {
compile ('com.aliyun.ams:alicloud-android-httpdns:1.3.1@aar') {
transitive true
}
}
获取httpdns实例,一参是Context 对象,即Android 中的上下文对象。
httpDnsService = HttpDns.getService(this, "xxxxxx");
设置预热域名,可以选择性地预先向HTTPDNS SDK中注册后续可能会使用到的域名,以便SDK提前解析,减少后续解析域名时请求的时延。
httpDnsService.setPreResolveHosts((ArrayList<String>) Arrays.asList("xxx.xxxx.io"));
获取ip地址
String ipAddress = httpDnsService.getIpByHostAsync(doman);
如果是用的okhttp作为底层的http通讯组件的话,有很好的接入方式。okhttp提供了dns的接口,我们自定义接口即可。
public class OkHttpDns implements Dns {
private static final Dns SYSTEM = Dns.SYSTEM;
HttpDnsService httpdns;//httpdns 解析服务
private static OkHttpDns instance = null;
private OkHttpDns(Context context) {
this.httpdns = HttpDns.getService(context, "account id");
}
public static OkHttpDns getInstance(Context context) {
if (instance == null) {
instance = new OkHttpDns(context);
}
return instance;
}
@Override
public List<InetAddress> lookup(String hostname) throws UnknownHostException {
//通过异步解析接口获取ip
String ip = httpdns.getIpByHostAsync(hostname);
if (ip != null) {
//如果ip不为null,直接使用该ip进行网络请求
List<InetAddress> inetAddresses = Arrays.asList(InetAddress.getAllByName(ip));
Log.e("OkHttpDns", "inetAddresses:" + inetAddresses);
return inetAddresses;
}
//如果返回null,走系统DNS服务解析域名
return Dns.SYSTEM.lookup(hostname);
}
}
经我实际测试,在对域名更换A解析后,TTL时间生效后,Android端能获得最新的ip地址。
我用的是免费版的域名解析,TTL最小是10分钟,也就是说免费版的话,最少也需要10分钟生效,不过也比运营商的缓存好多了,很多时候更改解析后,运营商那边半个多小时都不一定能更新缓存。
当然,也可以选择升级域名解析,比如这个企业旗舰版,TTL能达到1秒。