本章节介绍了HTTPDNS Android SDK的接入方法。
前提条件
如果要手动集成,需要下载SDK包,最新版本为V2.3.0-intl。
样例代码
HTTPDNS Android SDK接入工程样例,请参见HTTPDNS Android Demo。
SDK已开源,如有特殊需求,可以自行更改源码进行使用,请参见httpdns-android-sdk。
集成步骤
Maven快速添加依赖
在build.gradle中添加Maven仓库地址:
allprojects { repositories { maven { url 'http://maven.aliyun.com/nexus/content/repositories/releases/' } } }
gradle添加依赖:
dependencies { compile 'com.aliyun.ams:alicloud-android-httpdns:2.3.0-intl' }
混淆配置
如果您的项目中使用Proguard等工具做了代码混淆,请保留以下配置:
-keep class com.alibaba.sdk.android.**{*;} -keep class com.ut.**{*;} -keep class com.ta.**{*;}
应用程序初始化
初始化配置服务(可选,2.2.1版本开始支持)
在获取服务实例之前,我们可以通过初始化配置,设置服务的一些属性,避免服务以默认配置运行。建议进行初始化配置,避免单独调用API产生的时序问题。不进行初始化配置,也不影响基础功能使用。此处是代码示例,参数说明请查看初始化配置。
// 初始化配置,调用即可,不必处理返回值。 new InitConfig.Builder() // 配置初始的region .setRegion(currentRegion) // 配置是否启用https,默认http .setEnableHttps(enableHttps) // 配置服务请求的超时时长,毫秒 .setTimeout(10 * 1000) // 配置是否启用本地缓存,默认不启用 .setEnableCacheIp(true) // 配置是否允许返回过期IP,默认允许 .setEnableExpiredIp(true) // 配置ipv4探测域名 .setIpProbeItems(list) // 配置接口来自定义缓存的ttl时间 .configCacheTtlChanger(ttlChanger) // 配置固定IP的域名列表,优化SDK的内部逻辑,减少解析频次 .configHostWithFixedIp(hostListWithFixedIp) // 针对哪一个account配置 .buildFor(accountID);
获取服务实例
HTTPDNS Android SDK以全局service实例的方式提供域名解析服务,您可以通过以下方式获取实例。
普通方式
HttpDnsService httpdns = HttpDns.getService(applicationContext, accountID); // 参数applicationContext是您Android App的Context // 参数accountID是系统分配的Account ID,当您开通HTTPDNS后,您可以在控制台获取到您对应的Account ID信息
鉴权方式
说明HTTPDNS SDK V1.1.3及以上版本支持鉴权方式,该方式需要在HTTPDNS控制台进行关闭非鉴权接口(请谨慎操作)详情请参见鉴权解析接口。
鉴权默认过期时间为10分钟。
为避免在日志中泄漏参数accountID/secretKey或App运行过程中产生的数据,建议线上版本关闭SDK调试日志。
由于所有用户使用统一的SDK接入,在接入过程中需要在代码中设accountID/secretKey参数,而此类参数与计量计费密切相关,为防止恶意反编译获取参数造成信息泄漏,建议您开启混淆,并进行App加固后再发布上线。
HttpDnsService httpdns = HttpDns.getService(applicationContext, accountID, secretKey); // 参数applicationContext是您Android App的Context // 参数accountID是系统分配的Account ID,当您开通HTTPDNS后,您可以在控制台获取到您对应的Account ID信息 // 参数secretKey是鉴权对应的secretKey
设置预解析域名
在您初始化程序时,可以选择性地预先向HTTPDNS SDK中注册您后续可能会使用到的域名,以便SDK提前解析,减少后续解析域名时请求的时延。
您只需调用以下接口:
ArrayList<String> hostList = new ArrayList<>(Arrays.asList("www.taobao.com", "www.aliyun.com")); httpdns.setPreResolveHosts(hostList);
注意预解析接口设置的同时会触发异步网络请求,应该在代码逻辑上确保调用预解析接口时,已经进行了必备的初始化设置。比如setHTTPSRequestEnabled: 需要在预解析接口之前调用,否则会导致预解析的相关IP采用HTTP请求。
注意事项
务必编写降级代码
降级代码指的是HTTPDNS无法获取期望结果时的处理代码。请参见设置降级策略相关接口。
记录从HTTPDNS获取的IP及sessionId
我们提供了用于解析问题排查的解决方案,需要您将从HTTPDNS获取的IP及sessionId记录到日志中,详情请参见如何使用“会话追踪方案”排查解析异常。
设置HTTP请求头HOST字段
标准的HTTP协议中服务端会将HTTP请求头HOST字段的值作为请求的域名信息进行解析。
使用HTTPDNS后,您可能需要将HTTP请求URL中的HOST字段替换为HTTPDNS解析获得的IP,这时标准的网络库会将您的IP赋值给HTTP请求头的HOST字段,进而导致服务端的解析异常(服务端认可的是您的域名信息,而非IP信息)。
为了解决这个问题,您可以主动设置HTTP请求HOST字段的值,如:
String originalUrl = "http://www.aliyun.com/"; URL url = new URL(originalURL); String originalHost = url.getHost(); // 异步接口获取IP String ip = httpdns.getIpByHostAsync(originalHost); HttpURLConnection conn; if (ip != null) { // 通过HTTPDNS获取IP成功,进行URL替换和HOST头设置 url = new URL(originalUrl.replaceFirst(originalHost, ip)); conn = (HttpURLConnection) url.openConnection(); // 设置请求HOST字段 conn.setRequestProperty("Host", originalHost); } else { conn = (HttpURLConnection) url.openConnection(); }
Cookie字段
部分网络库支持Cookie的自动存储管理,当您使用HTTPDNS进行IP URL请求时,部分网络库会将您URL中的IP信息作为Cookie对应的域名信息进行存储管理(而非HTTP请求头HOST字段信息),进而造成Cookie管理与使用上的困扰,因此您需要关闭Cookie的自动管理功能(默认关闭)。
HTTPS/WebView/SNI场景
HTTPS场景,参考Android端HTTPS(含SNI)业务场景:IP直连方案。
WebView场景,参考Android端HTTPDNS+Webview最佳实践。
代理情况下的使用
当存在中间HTTP代理时,客户端发起的请求中请求行会使用绝对路径的URL,在您开启HTTPDNS并采用IP URL进行访问时,中间代理将识别您的IP信息并将其作为真实访问的HOST信息传递给目标服务器,这时目标服务器将无法处理这类无真实HOST信息的HTTP请求。
移动网关提供了
X-Online-Host
的私有协议字段来解决这个问题,比如:目标URL:http://www.example.com/product/oss/ 通过HTTPDNS解析出来的www.example.com的IP:192.168.XX.XX 代理:10.0.XX.XX:XX 您的HTTP请求头: GET http://192.168.XX.XX/product/oss/ HTTP/1.1 # 通过代理发起的HTTP请求头,请求行是一个绝对路径 Host: www.example.com # 这个Header会被代理网关忽略,代理网关会使用请求行绝对路径中的host字段作为源站的host,即192.168.XX.XX X-Online-Host: www.example.com # 这个Header就是移动网关为了传递真实Host添加的私有头部,源站需要配置识别该私有头部以获取真实的Host信息
同样您可以通过
setRequestProperty
方法进行X-Online-Host
请求头域的设置,并在服务端设置对该私有头域的解析。说明在绝大多数场景下,我们建议您在代理模式下关闭HTTPDNS功能。