目录
1、Dns
2、HttpDns
1、Dns
终端向LocalDNS发起递归查询。
LocalDNS(未开启转发模式),则向根DNS服务器发起迭代查询请求。(如开启转发模式,则转发至上级localDns)
(任何LocalDNS都需知道根DNS服务器的IP地址(全球共13台)。)
- 根DNS服务器返回一级域名服务器IP地址,(com DNS服务器的IP地址)。
(LocalDNS将com DNS服务器及其IP地址加入到缓存,下次DNS请求,在缓存未过期的情况下,授权给com 区的域名需向com DNS服务器请求查询时,直接往com DNS服务器发查询请求,不再向根DNS服务器请求。)
LocalDNS服务器向一级域名服务器(com DNS服务器)发起迭代查询请求。
com DNS服务器返回二级域名服务器IP地址(wangsu.com DNS服务器的IP地址)。
(LocalDNS将wangsu.comDNS服务器及其IP地址加入到缓存,下次DNS请求,在缓存未过期的情况下,授权给wangsu.com区的域名需向wangsu.com DNS服务器请求查询时,直接往对应 DNS服务器发查询请求,不再向根DNS服务器及com DNS服务器请求。)
- LocalDNS服务器向wangsu.com DNS服务器发起迭代查询请求。
7.wangsu.com DNS服务器给出域名的IP地址。
(LocalDNS将www.wangsu.com
IP地址加入到缓存,下次相同的DNS请求,在缓存未过期的情况下,LocalDNS直接给出该域名的IP地址,不再向权威DNS服务器查询。)
- LocalDNS服务器将该域名对应的IP地址返回给终端用户,
(DNS客户端将域名对应的IP地址接入缓存。下次请求该域名时,若缓存未过期,DNS客户端直接从缓存取出IP,不再向LocalDNS发起迭代查询。)
递归查询指如果终端用户所请求的LocalDNS服务器不知道被查询的域名的IP地址,则以DNS客户端的身份,向其它域名服务器继续发出查询请求报文(即替主机继续查询),而不是让主机自己进行下一步查询。因此,递归查询返回的查询结果或者是所要查询的IP地址,或者是报错,表示无法查询到所需的IP地址。
迭代查询指域名服务器或者给出最终结果,或者告诉DNS客户(此处指LocalDNS)应去哪些DNS服务器查询。
递归查询LocalDNS如果没有记录客户端发过来的域名对应的ip地址,则以客户端的身份,根域名服务器发起迭代查询,迭代查询是值,根域名服务器不直接告诉LocalDNS结果,而是告诉LocalDNS去哪里查询,然后LocalDNS一级一级的查询,直至最终得到结果。
2、httpdns
2.1、httpdns解决的问题
2.1.1、域名劫持
1、黑客侵入了宽带路由器并对Local DNS进行篡改;
2、攻击者还可以监听终端用户的域名解析请求,并在Local DNS返回正确结果之前将伪造的DNS解析响应传递给终端用户
3、Local DNS针对部分域名的缓存进行更改
2.1.2、调度不精准
由于运营商策略的多样性,其 Local DNS 的解析结果可能不是最近、最优的节点。
部分Local DNS A供应商为了降低运营成本,会将请求到自己节点的域名解析请求转发给其他供应商的Local DNS B节点,Local DNS B请求权威dns解析时,权威dns会根据Local DNS B的ip,分配离Local DNS B地理位置最近的ip地址。
Local DNS的布点受成本因素制约分布并不均匀也会导致上述调度不准的问题。
2.2、HTTPDNS
1、使用HTTP协议进行域名解析,将域名解析请求直接发送到HTTPDNS服务端,绕过运营商 Local DNS ,避免域名劫持。
2、HTTPDNS服务端会将终端用户的IP信息直接交付给权威DNS,从而解决调度不精准的问题。
3、另外通过域名预解析、缓存(DNS解析结果)、(解析结果)懒更新策略等方式实现无延迟解析。
2.2.1、预加载
app启动时,可以对我们后续需要用到的域名,调用HTTPDNS SDK中的预解析方法发起异步的预解析请求。
2.2.2、懒更新
所谓懒加载策略,核心的实现思路如下:
1、如果缓存中没有记录,那么异步网络请求HTTPDNS解析,获取解析结果。
(网络请求需要异步,同步调用需要直接拿到结果,可采取线程池+Future的策略)
2、如果缓存中存在记录,不论过期与否,直接返回业务层缓存中的记录;
3、如果缓存中的记录已过期,后台发起异步网络请求进行HTTPDNS解析;
绝大多数场景下域名对应IP变更并不频繁,特别是在单次APP的使用周期内,域名解析出的IP往往是相同的。
另一方面,即使域名对应的IP发生改变,后台会异步发起的异步HTTPDNS解析解析会很快获取最新解析结果 ,结合我们的网络重试策略,保证了下一次网络请求的正确性。
2.2.3、OKhttp+HttpDns
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 = httpdnsManager.getIpByHost(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);
}
}
//给okhttpclient设置自定义的dns
private void okhttpDnsRequest() {
OkHttpClient client = new OkHttpClient.Builder()
.dns(OkHttpDns.getInstance(getApplicationContext()))
.build();
自定义一个类实现Dns,并重写Dns的lookup方法,
在这个方法中结合懒更新策略获取域名对应的ip,包装成InetAddress list进行返回。