之前写过一篇文章 Android 使用OkHttp支持HttpDNS,该文章中使用的是OkHttp的拦截器来实现HttpDNS。在请求发出去之前,将URL中的域名替换成ip,再往Header中添加Host。这种方式有以下优点。

  • 上层方便控制哪些请求使用了HttpDNS,可以做相应的容灾处理,比如ip请求失败时使用域名进行重试。

同样的也有很多缺点。

  • Https场景下ip直连出现的证书校验问题
  • 代理场景下的HttpDNS问题
  • ip访问的时候Cookie的问题

于是,不得不寻找一种更加的解决方案,OkHttp其实暴露了一个Dns接口,默认的实现是使用系统的方法发送udp请求进行dns解析。于是,我们就可以实现一个Dns接口,解析的方式使用httpdns,将解析结果返回,接口实现之后将系统默认的Dns接口替换成我们的Dns接口。

首先,新建HttpDns类,实现Dns接口。内部维持一个系统默认的Dns对象。

public class HttpDns implements Dns {private static final Dns SYSTEM = Dns.SYSTEM;@Overridepublic List<InetAddress> lookup(String hostname) throws UnknownHostException {Log.e("HttpDns", "lookup:" + hostname);return SYSTEM.lookup(hostname);}
}

我们只需要在lookup方法中调用HttpDns的SDK去获取IP,如果获取到的ip非空,并且ttl没有过期,则使用HttpDns。完整的方法的代码如下

public class HttpDns implements Dns {private static final Dns SYSTEM = Dns.SYSTEM;@Overridepublic List<InetAddress> lookup(String hostname) throws UnknownHostException {Log.e("HttpDns", "lookup:" + hostname);String ip = DNSHelper.getIpByHost(hostname);if (ip != null && !ip.equals("")) {List<InetAddress> inetAddresses = Arrays.asList(InetAddress.getAllByName(ip));Log.e("HttpDns", "inetAddresses:" + inetAddresses);return inetAddresses;}return SYSTEM.lookup(hostname);}
}

DNSHelper类中做的就是将域名转换为ip,具体转换过程涉及到缓存,这里不展开,可以参考新浪的HTTPDNS库https://github.com/CNSRE/HTTPDNSLib

之后初始化OkHttp的时候将Dns替换为HttpDns对象。

 OkHttpClient client = new OkHttpClient.Builder().dns(new HttpDns()).build();

这样,使用client对象发出去的请求都是走httpdns解析dns的,除非没有命中httpdns缓存。

这样做有什么好处呢?这样做相当于还是用域名进行访问,只不过底层的dns解析换成了http协议。也就是和之前系统的dns解析没有差别,但是得保证httpdns返回的ip是正确的。

  • https下不会存在任何问题,证书校验依然使用域名进行校验
  • cookie的问题也自然不存在。

同样的,解决了一部分问题后,也有一部分的风险。风险在哪呢?

  • 过于底层,容灾不好做,除非强制关闭Httpdns。
  • 服务器返回的ip如果不正确,这次请求就挂了,甚至下次也可能挂了。
  • OkHttp默认对解析结果有一定时间的缓存,万一ttl过期了,okhttp可能依然会去使用,这时候也是有风险的。

对比两种方案,各有各的优点,一个方便做容灾,但同时也暴露出了很多问题,一个不方便做容灾,但是之前暴露出来的问题都不存在。所以,这时候就得根据实际情况衡量选择哪一种方案了。

还有就是WebView的HttpDns,目前看来Android的Webview简直就是一个Bug的存在,没有什么好的解决方法。在IOS中,Webview的请求是一个正常的HttpRequest对象,不会像Android中存在这种问题,Andorid中比较好的解决方法就是在native层的网络库里开一个代理服务器,将Webview的所有请求转发至这个代理服务器,由这个代理服务器将请求通过httpdns转换成ip请求,将请求结果返回给webview。

或者通过WebView的资源拦截接口拦截资源请求,不过这种方式只能处理资源,处理正常的http/https请求会存在问题,在Android5.0以下存在cookie种不进去的问题。

总之WebView就是蛋疼的存在,没有什么好的办法,除非有自己的Webview的容器~

Android OkHttp实现HttpDns的最佳实践(非拦截器)相关推荐

  1. Android OKHttp 可能你从来没用过的拦截器 【实用推荐】

    前言 在平时开发中,你有没有下面这样的困扰呢? 场景一 明明是服务端的接口数据错误,而QA(测试)第一个找到的可能是客户端开发的你,为什么这个页面出现错误了? 而作为客户端开发的你,可能要拿出测试机连 ...

  2. 【Android】OkHttp源码解读逐字稿(1)-拦截器

    目录 0.前言 1.OkHttp的简单使用 2.浅析开始 拦截器 链式调用流程示意图 第 0 个拦截器 第一个 拦截器 RetryAndFollowUpInterceptor 第二个拦截器 Bridg ...

  3. Android 6.0 权限管理最佳实践

    博客: Android 6.0 运行时权限管理最佳实践 github: https://github.com/yanzhenjie/AndPermission

  4. Android车辆运动轨迹大数据采集最佳实践

    csdn源码下载地址:https://download.csdn.net/download/geduo_83/10841480 前言: 最近帝都的天气有些冷,天寒地冻,天气虽冷,但也无法阻挡我写文章的 ...

  5. Android 加载GIF图最佳实践

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/75578109 本文出自[赵彦军的博客] 起因 最近在项目中遇到需要在界面上显示一个 ...

  6. android 权限管理框架,Android 运行时权限管理最佳实践

    欢迎访问我的个人博客 传送门 从 Android 6.0(API 级别 23)开始,用户开始在应用运行时向其授予权限,而不是在应用安装时授予.此方法可以简化应用安装过程,因为用户在安装或更新应用时不需 ...

  7. Okhttp 接入HttpDNS(支持http/https,)达到IP直连

    HttpDns 是什么? HTTPDNS 利用 HTTP 协议与 DNS 服务器交互,代替了传统的基于 UDP 协议的 DNS 交互,绕开了运营商的 Local DNS,有效防止了域名劫持,提高域名解 ...

  8. Android开发最佳实践---Futurice之见

    原文链接:https://github.com/futurice/android-best-practices 本文是Futurice公司的Android开发人员总结的最佳实践,遵循这些准则可以避免重 ...

  9. android double精度_Android车辆运动轨迹平滑移动(高仿滴滴打车)最佳实践

    点击上方"Android技术杂货铺",选择"标星" 干货文章,第一时间送达! 作者:门心叼龙 链接:https://www.jianshu.com/p/015b ...

最新文章

  1. 服务器网页500错误修复工具,HTTP500错误是什么?如何修复
  2. Struts2利用iText导出word文档(包含表格)
  3. __init__()
  4. CentOS安装网络代理软件
  5. professional asp.net 4 with c# and VB.net 阅读笔记
  6. 【spring-session】错误:No bean named 'springSessionRepositoryFilter' available
  7. C# mysql 插入数据,中文乱码
  8. sql多语句表值函数_构造一个特殊的多语句表函数来检查SQL Server的运行状况
  9. [转载] Python OpenCV 基础教程
  10. 2 网段 Vlan+NAT 配置
  11. Android 屏幕画笔实现
  12. AutoCAD 安装
  13. 日剧推介:怨み屋本舗
  14. 计算机网络保密承诺书,保密承诺书集合5篇
  15. CompletableFuture模拟复杂场景使用测试。。。
  16. 两个div实现十字架
  17. Django实现用户管理
  18. Word2Vec教程 - Skip-Gram模型
  19. 【Origin】羡旁人
  20. 刚刚从Java培训班出来以及初学者怎么样才能通过面试?

热门文章

  1. mt6582 pwm
  2. Explaining and Harnessing Adversarial Examples——论文的学习笔记01
  3. unzip和zip指令的使用方法
  4. 基于平移布林通道的系统
  5. linux panic机制
  6. 环形链表。给定一个链表,判断链表中是否有环。(GO、PHP)
  7. 记一次神奇的CVPR 2021 Rebuttal 经历
  8. MDC实现日志链路追踪
  9. 监控页面所有 ajax请求
  10. JWT整合springboot 自定义定时更换秘钥