通過用戶端接入概述您已經瞭解了HTTPDNS接入的基本原理,本文介紹通過Android SDK接入HTTPDNS的方法。
前言
本章節介紹HTTPDNS Android SDK的接入方法。
推薦使用Gradle管理依賴的Android Studio專案。
支援Android 4.4(API Level 19)及以上版本。
targetSdkVersion支援到Android 14(API = 34)。
支援arm64-v8a/armeabi-v7a/x86/x86_64架構。
SDK已開源,如有特殊需求,可以自行更改源碼進行使用,請參見httpdns-android-sdk。
第一步:將SDK添加到您的應用
我們提供了Maven依賴和本地依賴兩種整合方式,方便您根據需要將SDK添加到您的應用中。
建議開發人員採用Maven依賴方式進行整合,配置簡單,不容易出問題,後續更新方便。
1 Maven依賴方式(推薦)
1.1 配置Maven倉庫
下面分別介紹Gradle 7.0及以上推薦的dependencyResolutionManagement配置方式和Gradle 7.0以下推薦的allprojects配置方式。
1.1.1 dependencyResolutionManagement方式
在您的根級(專案級)Gradle 檔案(<project>/settings.gradle)中,在dependencyResolutionManagement的repositories中添加Maven倉庫地址。
dependencyResolutionManagement {
repositories {
maven {
url 'https://maven.aliyun.com/nexus/content/repositories/releases/'
}
}
}1.1.2 allprojects方式
在您的根級(專案級)Gradle 檔案(<project>/build.gradle)中,在allprojects的repositories中添加Maven倉庫地址。
allprojects {
repositories {
maven {
url 'https://maven.aliyun.com/nexus/content/repositories/releases/'
}
}
}1.2 添加SDK依賴
在您的模組(應用級)Gradle 檔案(通常是<project>/<app-module>/build.gradle)中,在dependencies中添加SDK依賴。
dependencies {
implementation 'com.aliyun.ams:alicloud-android-httpdns:${httpdnsVersion}'
}httpdnsVersion請從Android SDK發布說明中擷取。
2 本地依賴方式
2.1 下載SDK
從EMAS SDK列表選擇HTTPDNS進行下載,將SDK包內所有檔案拷貝至您的模組(應用級)的<project>/<app-module>/libs目錄下。
2.2 添加SDK依賴
2.2.1 配置本地SDK目錄
在您的模組(應用級)Gradle 檔案(通常是<project>/<app-module>/build.gradle)中,添加本地SDK檔案目錄位址。
repositories {
flatDir {
dirs 'libs'
}
}2.2.2 添加SDK依賴
在您的模組(應用級)Gradle 檔案(通常是<project>/<app-module>/build.gradle)中,在dependencies中添加SDK依賴。
dependencies {
implementation (name: 'alicloud-android-httpdns-${httpdnsVersion}', ext: 'aar')
implementation (name: 'alicloud-android-logger-${loggerVersion}', ext: 'aar')
implementation (name: 'alicloud-android-crashdefend-${crashDefendVersion}', ext: 'jar')
implementation (name: 'alicloud-android-ipdetector-${ipdetectorVersion}', ext: 'aar')
implementation 'commons-codec:commons-codec:1.15'
}樣本依賴中的SDK版本號碼請根據下載產物的檔案名稱中的版本號碼為準。
如果編譯過程中報類缺失,請確認dependencies下是否已經有
implementation fileTree(dir: 'libs', include: ['*.jar'])
第二步:配置使用SDK
1 配置HTTPDNS
//初始化配置,調用即可,不必處理傳回值。
InitConfig config = InitConfig.Builder()
/*
(可選)設定應用安裝後首次網域名稱解析訪問的HTTPDNS服務叢集,後續解析請求會依據用戶端網路就近訪問,需明確選取目的地區域,可選Region為Region.SG、Region.HK、Region.US、Region.DE。
*/
.setRegion(Region.SG)
/*
(必填)傳入應用 Context,用於網路變化事件感知等,通常傳 ApplicationContext 即可。
*/
.setContext(context)
/*
(可選)配置與服務端互動的加簽秘鑰,可防止請求被篡改,預設不開啟,建議開啟。
*/
.setSecretKey(secretKey)
/*
(可選) 配置SDK與服務端互動的傳輸層協議,開啟後可獲得更高的鏈路安全性,同時需關注 HTTP 與 HTTPS 在計費邏輯上的差異,預設HTTP協議,建議開啟。
*/
.setEnableHttps(enableHttps)
/*
(可選)設定網域名稱解析逾時時間,毫秒,最大5000ms,預設2000ms。
*/
.setTimeoutMillis(2 * 1000)
/*
(可選)配置是否啟用本機快取,用於最佳化啟動後的網域名稱解析環節耗時,進而提升首屏載入速度,預設不啟用,建議開啟並設定緩衝時間為1天。
*/
.setEnableCacheIp(true, 24 * 60 * 60 * 1000)
/*
(可選)設定是否允許使用到期緩衝,若啟用“複用到期IP”選項,介面可立即返回上次的到期IP以減少阻塞並提升請求效能,同時SDK會在後台非同步重新整理最新解析,預設開啟。
*/
.setEnableExpiredIp(true)
/*
(可選)設定對解析結果的IP列表進行嗅探排序,設定嗅探的網域名稱和探測連接埠的列表,對延遲敏感的請求,建議配置
*/
.setIPRankingList(ipRankingItemJson.toIPRankingList())
/*
(可選) 配置介面來自訂緩衝的ttl時間,以改變的權威DNS預設緩衝TTL
*/
.configCacheTtlChanger(ttlChanger)
/*
(可選) 部分網域名稱的IP是相對穩定的,這部分網域名稱的緩衝在網路變化等情境下可以不用頻繁重新整理,可以通過該介面顯式告訴SDK
*/
.configHostWithFixedIp(hostListWithFixedIp)
/*
(可選)配置不使用HTTPDNS解析的網域名稱篩選條件,對於列表中的網域名稱,HTTPDNS立即返回空
*/
.setNotUseHttpDnsFilter(notUseHttpDnsFilter)
.build()
HttpDns.init(accountID, config);//初始化配置,調用即可,不必處理傳回值。
InitConfig config = new InitConfig.Builder()
/*
(可選)設定應用安裝後首次網域名稱解析訪問的HTTPDNS服務叢集,後續解析請求會依據用戶端網路就近訪問,若業務不希望首次訪問到預設叢集,可在此明確選取目的地區域(如 Region.SG、Region.HK),中國站預設中國大陸,國際站預設新加坡叢集。
*/
.setRegion(Region.SG)
/*
(必填)傳入應用 Context,用於網路變化事件感知等,通常傳 ApplicationContext 即可。
*/
.setContext(context)
/*
(可選)配置與服務端互動的加簽秘鑰,可防止請求被篡改,預設不開啟,建議開啟。
*/
.setSecretKey(secretKey)
/*
(可選) 配置SDK與服務端互動的傳輸層協議,開啟後可獲得更高的鏈路安全性,同時需關注 HTTP 與 HTTPS 在計費邏輯上的差異,預設HTTP協議,建議開啟。
*/
.setEnableHttps(enableHttps)
/*
(可選)設定網域名稱解析逾時時間,毫秒,最大5000ms,預設2000ms。
*/
.setTimeoutMillis(2 * 1000)
/*
(可選)配置是否啟用本機快取,用於最佳化啟動後的網域名稱解析環節耗時,進而提升首屏載入速度,預設不啟用,建議開啟並設定緩衝時間為1天。
*/
.setEnableCacheIp(true, 24 * 60 * 60 * 1000)
/*
(可選)設定是否允許使用到期緩衝,若啟用“複用到期IP”選項,介面可立即返回上次的到期IP以減少阻塞並提升請求效能,同時SDK會在後台非同步重新整理最新解析,預設開啟。
*/
.setEnableExpiredIp(true)
/*
(可選)設定對解析結果的IP列表進行嗅探排序,設定嗅探的網域名稱和探測連接埠的列表,對延遲敏感的業務,建議配置
*/
.setIPRankingList(ipRankingItemJson.toIPRankingList())
/*
(可選) 配置介面來自訂緩衝的ttl時間,以改變的權威DNS預設緩衝TTL
*/
.configCacheTtlChanger(ttlChanger)
/*
(可選) 部分網域名稱的IP是相對穩定的,這部分網域名稱的緩衝在網路變化等情境下可以不用頻繁重新整理,可以通過該介面顯式告訴SDK
*/
.configHostWithFixedIp(hostListWithFixedIp)
/*
(可選)配置不使用HTTPDNS解析的網域名稱篩選條件,對於列表中的網域名稱,HTTPDNS立即返回空
*/
.setNotUseHttpDnsFilter(notUseHttpDnsFilter)
.build()
HttpDns.init(accountID, config);通過配置
setEnableExpiredIp(true)和setEnableCacheIp(true, 24 * 60 * 60 * 1000)可以實現樂觀DNS緩衝,使網域名稱解析結果在本機快取並允許使用到期 IP,從而使大部分 DNS 解析在本地完成,對於業務網域名稱解析結果IP不頻繁變更的網域名稱,建議開啟,詳細資料可參考setEnableCacheIp和setEnableExpiredIp。setEnableHttps參數設定為true後,計費會增加,請仔細閱讀產品計費文檔。
如果您對網域名稱資訊或SDNS參數有更高的安全訴求,可以使用setAesSecretKey介面啟用對解析請求進行內容層加密,但使用AES內容加密後計費會增加,開啟前請務必仔細閱讀產品計費文檔。
如果初始化的時候
setEnableHttps沒有設定成true,需要在應用級的AndroidManifest.xml檔案下的application節點下添加配置android:usesCleartextTraffic="true",否則網域名稱解析請求在高版本(targetSdkVersion 27及以上)系統上會失敗。
具體配置介面資訊請查看配置介面。
2 擷取服務執行個體
HTTPDNS Android SDK以全域service執行個體的方式提供網域名稱解析服務,您可以通過以下方式擷取執行個體。
val httpdns = HttpDns.getService(accountID)HttpDnsService httpdns = HttpDns.getService(accountID);3 佈建網域名預解析
完成HTTPDNS初始化後,可以對後續可能用到的熱點網域名稱配置預解析,以便SDK提前解析,減少後續網域名稱解析時請求的時延。
val hostList = arrayListOf<String>()
hostList.add("www.aliyun.com")
httpdns.setPreResolveHosts(hostList)ArrayList<String> hostList = new ArrayList<>();
hostList.add("www.aliyun.com");
httpdns.setPreResolveHosts(hostList);啟用網域名稱預解析可顯著提升樂觀 DNS 緩衝的命中率,使大部分解析請求直接從本機快取返回,減少即時解析帶來的時延。
預解析會增加解析請求量,建議僅對核心業務網域名稱 / 高頻訪問網域名稱開啟,以獲得最佳效能與成本平衡。
4 進行網域名稱解析
HTTPDNS提供了多種網域名稱解析方式,包括同步解析、非同步解析和同步非阻塞解析。下面以同步非阻塞解析介面作為例子。
val httpDnsResult = httpdns.getHttpDnsResultForHostSyncNonBlocking("www.aliyun.com", RequestIpType.auto)HTTPDNSResult httpDnsResult = httpdns.getHttpDnsResultForHostSyncNonBlocking("www.aliyun.com", RequestIpType.auto);getHttpDnsResultForHostSyncNonBlocking 該介面僅查詢快取,返回緩衝查詢的解析結果。若緩衝中沒有解析結果或者緩衝中的解析結果已經TTL到期,則會在背景工作執行緒中進行網域名稱解析,解析成功後更新緩衝,供下次調用網域名稱解析使用。
配合預解析setPreResolveHosts、持久化緩衝setEnableCacheIp和允許到期介面setEnableExpiredIp,能使得絕大多數的解析請求命中本機快取,實現0ms解析延遲。
若您的業務強依賴HTTPDNS解析的結果,比如使用自訂解析、Local DNS劫持嚴重,需要使用getHttpDnsResultForHostSync或getHttpDnsResultForHostAsync。
5 使用網域名稱解析結果
上一步解析成功後,可以獲得網域名稱解析結果,資料結構請查看HTTPDNSResult。
此處以okhttp網路程式庫的解析過程為例,範例程式碼如下:
object : Dns {
@Throws(UnknownHostException::class)
override fun lookup(host: String): List<InetAddress> {
val httpdnsResult: HTTPDNSResult = HttpDns.getService(accountID)
.getHttpDnsResultForHostSyncNonBlocking(host, RequestIpType.auto)
val inetAddresses: MutableList<InetAddress> = ArrayList()
var address: InetAddress
try {
if (httpdnsResult.ips != null) {
//處理IPv4地址
for (ipv4 in httpdnsResult.ips) {
address = InetAddress.getByName(ipv4)
inetAddresses.add(address)
}
}
if (httpdnsResult.ipv6s != null) {
//處理IPv6地址
for (ipv6 in httpdnsResult.ipv6s) {
address = InetAddress.getByName(ipv6)
inetAddresses.add(address)
}
}
} catch (e: UnknownHostException) {
}
return if (!inetAddresses.isEmpty()) {
inetAddresses
// 重要:配置降級LocalDNS
} else Dns.SYSTEM.lookup(host)
}
}new Dns() {
@Override
public List<InetAddress> lookup(String host) throws UnknownHostException {
HTTPDNSResult httpdnsResult = HttpDns.getService(accountID).getHttpDnsResultForHostSync(host, RequestIpType.auto);
List<InetAddress> inetAddresses = new ArrayList<>();
InetAddress address;
try {
if (httpdnsResult.getIps() != null) {
//處理IPv4地址
for (String ipv4 : httpdnsResult.getIps()) {
address = InetAddress.getByName(ipv4);
inetAddresses.add(address);
}
}
if (httpdnsResult.getIpv6s() != null) {
//處理IPv6地址
for (String ipv6 : httpdnsResult.getIpv6s()) {
address = InetAddress.getByName(ipv6);
inetAddresses.add(address);
}
}
} catch (UnknownHostException e) {
}
if (!inetAddresses.isEmpty()) {
return inetAddresses;
}
return Dns.SYSTEM.lookup(host);
}
};6 混淆配置
如果您的專案做了代碼混淆,請保留以下混淆配置。
-keep class com.alibaba.sdk.android.**{*;}第三步:接入驗證
接入驗證封裝括兩個環節:1)通過SDK擷取了網域名稱對應的IP地址;2)網路程式庫使用了HTTPDNS SDK返回的IP,並且訪問商務服務成功。
1 驗證IP擷取成功
確認 HTTPDNS SDK 已成功解析出目標網域名稱的 IP 位址。您可以通過以下兩種方式驗證:
查看解析日誌: 在 EMAS 控制台查看 HTTPDNS 解析日誌。若日誌中顯示目標網域名稱對應的 IP 列表,說明解析成功。
列印 SDK 返回結果:在代碼中直接列印 HTTPDNS SDK 的解析回調結果,檢查是否返回有效 IP。
# 發起同步請求 D sync request host www.aliyun.com with type both extras : null cacheKey null # 緩衝查詢結果 D host www.aliyun.com result in cache is null # 觸發雲端解析 I sync start request for www.aliyun.com both D ip detector type is 3 D ipdetector type is both D start resolve ip request for www.aliyun.com both # 解析逾時時間長度 D the httpDnsConfig timeout is: 2000 D final timeout is: 2000 D wait for request finish # 發起解析請求 D request url http://xx.xx.xx.xx:80/xxxx/sign_d?host=www.aliyun.com&sdk=android_2.4.0&query=4,6&sid=CaZk1vTyI3hy&s=b4a34694b7215b4cd6a10376b3425a8e&t=1715772172 # 解析成功 D request success {"ipsv6":[],"host":"www.aliyun.com","ips":[],"ttl":60,"origin_ttl":60} # 更新緩衝 D save host www.aliyun.com for type v4 ttl is 60 D save host www.aliyun.com for type v6 ttl is 60 D sync resolve time is: 224 # 返回解析結果 I request host www.aliyun.com for both and return host:www.aliyun.com, ips:[], ipv6s:[], extras:{}, expired:false, fromDB:false after request
2 驗證網路程式庫驗證成功
網路程式庫接入HTTPDNS成功的標準是DNS解析是否繞過了LocalDNS,使用了HTTPDNS。您可以通過以下兩種方式進行驗證:
注意事項
升級SDK後編譯失敗
如果您升級SDK版本後,出現編譯失敗的情況,有可能是因為SDK的API有調整,請查看Android SDK API使用替換的新介面。
務必編寫降級代碼
降級代碼指的是當HTTPDNS無法擷取期望結果時,需要降級使用Local DNS去完成網域名稱解析。
記錄從HTTPDNS擷取的IP及sessionId
我們提供了用於解析問題排查的解決方案,需要您將從HTTPDNS擷取的IP及sessionId記錄到日誌中,詳情請參見如何使用“會話追蹤方案”排查解析異常。