全部产品
Search
文档中心

云解析 DNS:Harmony SDK开发指南

更新时间:Mar 27, 2026

本文档介绍了移动解析HTTPDNS Harmony SDK的接入和开发方式。

安装SDK

支持使用DevEco Studio 自动导入手动导入两种方式,将SDK 导入到您的应用工程中,您可以参考Demo示例工程源码了解如何使用本SDK。

  • 自动导入,使用ohpm从OpenHarmony三方库中心仓安装。

    2.0.1版本开始支持从OpenHarmony三方库中心仓 获取SDK

    在工程的根目录执行

    ohpm install @alidns/httpdns

    ohpm工具以及更多关于OpenHarmony安装第三方SDK的信息请参考OpenHarmony三方库中心仓说明

  • 手动导入,引用本地HAR包方式集成SDK。

    参考SDK下载,获取鸿蒙SDK,并集成SDK在自己的App工程项目中

    在工程的oh-package.json5中设置三方包依赖。以HAR包在工程根目录下为例,配置示例如下(实际配置时请以HAR包实际目录为准):

    "dependencies": {
        "@alidns/httpdns": "file:alidns-harmony-sdk-2.0.1.har"
     }

    依赖设置完成后,需要执行ohpm install命令安装依赖包,依赖包会存储在工程的oh_modules目录下。

    ohpm install

使用SDK

引入头文件

import { Alipdns,schemaType,DNSDomainInfo, DNSLogger } from '@alidns/httpdns'

设置鉴权模式

开启鉴权模式,以保障用户身份安全,不被第三方未授权者盗用,用户在Alibity onCreate生命周期回调中执行以下代码配置SDK。

重要

参考创建密钥在控制台创建AccessKey ID 和 AccessKey Secret

import { Alipdns,schemaType,DNSDomainInfo, DNSLogger } from '@alidns/httpdns'

const AccountID = '这里需要替换为设置您在控制台接入SDK的Account ID';
const AccessKeID = '这里需要替换为您在控制台“接入配置”创建的密钥的 AccessKey ID';
const AccessKeySecret = '这里需要替换为您在控制台“接入配置”创建的密钥的 AccessKey Secret';

export default class EntryAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    // ************* 阿里pdns-sdk配置 begin *************
    DNSLogger.getInstance().setEnableLogger = true;
    let alipdns = Alipdns.getInstance();
    alipdns.Init(this.context,AccountID,AccessKeID,AccessKeySecret);
    alipdns.setKeepAliveDomains(['*****','*****']);
    alipdns.setSchemaType(schemaType.https);
    alipdns.preLoadDomains(alipdns.QTYPE_V4,['*****','*****','*****']);
    // ************* 阿里pdns-sdk配置 end *************
  }

  // 省略其它代码
}

API介绍

1. Account ID和鉴权

必传参数,您在控制台注册自己的应用后,控制台会为此应用生成唯一标识Account ID,鉴权功能来保障用户身份安全,防止被第三方未授权者盗用。用户请参考创建密钥在控制台创建AccessKey,并在APP中通过如下代码设置:

Alipdns.getInstance().Init(this.context,AccountID,AccessKeID,AccessKeySecret);
警告
  • 为避免在日志中泄漏参数Account ID/AccessKey ID/AccessKey Secret或App运行过程中产生的数据,建议线上版本关闭SDK调试日志。

  • Account ID、AccessKey ID 和 AccessKey Secret此类参数与计量计费密切相关,为防止恶意反编译获取参数造成信息泄露,在生产环境中,您需要避免直接传入明文。例如,您可以预先把明文进行编码或加密处理,在传值的时候再对已编码或加密的明文进行解码或解密。同时,建议您对 app 进行代码混淆处理并加固。否则,您的Account ID、AccessKey ID 和 AccessKey Secret可能会被第三方通过反编译的方式获得。

2. 解析协议设置

SDK支持设置DNS解析请求协议类型,可自主选择通过HTTP或HTTPS协议解析,具体可通过scheme属性进行设置。

SDK默认并推荐使用HTTPS协议进行解析,因为HTTPS协议安全性更好。移动解析HTTPDNS的计费项是按HTTP的解析次数进行收费,其中HTTPS是按5倍HTTP流量进行计费,开发者可以根据自身实际业务需要选择scheme类型。如下设置:

Alipdns.getInstance().setSchemaType(schemaType.https);

3. 设置域名缓存保持

SDK在缓存功能已开启的情况下,可设置针对某些域名开启缓存保持功能,如果该功能开启,SDK会自动更新这些域名的过期缓存,保障用户缓存数据及时更新,但是可能会带来域名解析次数和客户端流量消耗的增多。如果不设置该功能,那么SDK不会自动进行过期缓存更新,只有当用户调用解析方法时,才会再次进行缓存更新。若要设置某些域名的缓存保持需要通过以下代码设置:

Alipdns.getInstance().setKeepAliveDomains(['*****','*****']);
说明
  • 优势:

    • 可及时(TTL过期前)更新记录。

    • 配合预加载可降低首次解析延迟(0ms)。

  • 劣势:缓存时间超过TTL*75%之后会再重新请求,会带来额外的费用。

4. 预解析

由于SDK可以设置开启缓存功能,在第一次解析完域名产生缓存后,后续再次解析此域名时解析速度可提升至0时延。因此,建议在app启动后,对app中可能要解析的域名进行预解析。

代码示例:

Alipdns.getInstance().preLoadDomains(alipdns.QTYPE_V4,['*****','*****','*****']);

5. 设置开启SDK调试日志开关

用户可以设置是否开启SDK调试日志开关(true为开启调试日志,false为关闭调试日志),该方法请在SDK初始化前设置。

DNSLogger.getInstance().setEnableLogger = true;

6. 设置是否开启使用 移动解析HTTPDNS 解析失败时自动降级到localdns进行兜底解析

SDK默认开启使用移动解析HTTPDNS解析失败时自动降级到localdns兜底解析

Alipdns.getInstance().setEnableLocalDns(true);//默认开启使用移动解析HTTPDNS解析失败时自动降级到localdns兜底解析

7. 设置域名解析的超时时间

timeout属性为域名解析的超时时间。默认超时时间为3s,用户可自定义超时时间,建议设置在2~5s之间。

Alipdns.getInstance().setTimeout(3);//默认超时时间为3s

8. 解析方法

SDK提供不同的域名解析方法,示例如下:

/// 异步解析方法
/// Alipdns.getInstance().QTYPE_V4           解析ip地址类型:ipv4
/// host                                     要解析的域名
/// ips                                      回调(所有ip地址)
Alipdns.getInstance().getIpsByHostAsync(Alipdns.getInstance().QTYPE_V4, host,(ips:string[]) => {});

/// 同步解析方法(取缓存中的数据)
/// Alipdns.getInstance().QTYPE_V4           解析ip地址类型:ipv4
/// host                                     要解析的域名
/// true                                     是否允许返回过期ip结果
const result = Alipdns.getInstance().getIpsByHostFromCache(Alipdns.getInstance().QTYPE_V4,host,true);

如何使用SDK

addCustomDnsRule方式

在发起网络请求之前,调用SDK的域名解析API进行DNS解析,通过connection.addCustomDnsRuleAPI配置DNS的解析结果,为当前应用程序添加自定义host和对应的IP地址的映射。以HTTP请求为例,代码如下:

import { http } from '@kit.NetworkKit';
import connection from '@ohos.net.connection';
import { Alipdns,schemaType,DNSDomainInfo } from '@alidns/httpdns'
import Url from '@ohos.url';

export async function requestWithHttpDns(url: string, options: http.HttpRequestOptions): Promise<http.HttpResponse> {
  let urlObject = Url.URL.parseURL(url);
  const host = urlObject.hostname;
  // ************* 移动解析HTTPDNS解析获取域名 begin *************
  const result = Alipdns.getInstance().getIpsByHostFromCache(Alipdns.getInstance().QTYPE_V4,host,true);
  // ************* 移动解析HTTPDNS解析获取域名 end *************
  // ************* 通过系统API设置DNS规则 begin *************
  try {
    await connection.removeCustomDnsRule(host);
  } catch (ignored) {
  }
  if (result.length ?? 0 > 0) {
    await connection.addCustomDnsRule(host, result);
  } else {
    console.log(`httpdns解析没有结果,不设置dns`);
  }
  // ************* 通过系统API设置DNS规则 begin *************
  // ************* 通过系统API进行网络请求 begin *************
  const httpRequest = http.createHttp();
  return httpRequest.request(url, options);
  // ************* 通过系统API进行网络请求 end *************
}
重要

HarmonyOS 如何定制DNS解析规则

HarmonyOS 提供了定制DNS解析规则的API:addCustomDnsRuleremoveCustomDnsRuleclearCustomDnsRules

通过addCustomDnsRule API应用可以添加自定义host和对应的IP地址的映射,

通过removeCustomDnsRule API应用可以删除对应host的自定义DNS规则,

通过clearCustomDnsRules API应用可以删除所有的自定义DNS规则。

因此,当应用想要定制网络请求的DNS规则时,可以在网络请求之前,通过上述API设置对应的规则,然后再发起网络请求。

Remote Communication Kit的dnsRules方式

当使用Remote Communication Kit包进行网络请求时,可以先调用SDK的域名解析API进行DNS解析,然后通过配置dnsRules字段,修改DNS规则,以fetch请求为例,代码如下:

import { Alipdns,schemaType,DNSDomainInfo } from '@alidns/httpdns'
import { rcp } from '@kit.RemoteCommunicationKit';
import Url from '@ohos.url';

export async function rcpWithHttpDns(url: string): Promise<rcp.Response> {
  let urlObject = Url.URL.parseURL(url);
  const host = urlObject.hostname;
  // ************* 移动解析HTTPDNS解析域名获取IP结果 begin *************
  const result = Alipdns.getInstance().getIpsByHostFromCache(Alipdns.getInstance().QTYPE_V4,host,true);
  // ************* 移动解析HTTPDNS解析域名获取IP结果 end *************
  const request = new rcp.Request(url, "GET");
  if (result.length ?? 0 > 0) {
      request.configuration = {
        dns: {
          // ************* 通过dnsRules设置IP begin *************
          dnsRules: [{ host, port: 443, ipAddresses: result },{ host, port: 80, ipAddresses: result }]
          // ************* 通过dnsRules设置IP end *************
        }
      }
    }
  // ************* 通过系统API进行网络请求 begin *************
  const session = rcp.createSession();
  return session.fetch(request);
  // ************* 通过系统API进行网络请求 end *************
}

域名解析最佳实践

预解析 + 允许过期回复,实现最佳性能

在对网络性能要求较高的场景中,结合「预解析」与「允许过期回复」策略,可显著提升 DNS 解析速度,甚至实现 “0 时延”解析。

得益于 SDK 内置的缓存机制,在完成预解析后,后续对该域名的解析请求可直接命中缓存,避免网络往返,极大优化用户体验。

1,预解析

启用缓存并预解析关键域名(推荐在 App 启动时执行)

在 EntryAbility 的 onCreate() 中,提前解析业务中使用的域名,将结果缓存至本地内存中。

1,适用于仅支持ipv4的场景

//********适用于仅支持ipv4的场景*******
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate');

    let alipdns = Alipdns.getInstance();
    alipdns.Init(this.context,AccountID,AccessKeID,AccessKeySecret);
    //预解析的IPV4记录类型 
    alipdns.preLoadDomains(alipdns.QTYPE_V4,['您要预加载的域名1','您要预加载的域名2']);
}

2,适用于需要支持ipv6的场景

//********适用于需要支持ipv6的场景*******
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate');

    let alipdns = Alipdns.getInstance();
    alipdns.Init(this.context,AccountID,AccessKeID,AccessKeySecret);
    //预解析的IPV4和IPV6记录类型  
    alipdns.preLoadDomains(alipdns.QTYPE_Auto,['您要预加载的域名1','您要预加载的域名2']);
}

2,允许过期回复

解析时优先使用缓存(允许返回过期 IP),在实际发起网络请求前,优先从缓存中获取 IP 地址,并允许使用已过期但尚未失效的缓存记录。这样即使 TTL 已过,只要缓存未被清除,仍可立即返回结果,实现“零等待”。

1,适用于仅支持ipv4的场景

    //********适用于仅支持ipv4的场景*******
    
    // ************* HTTPDNS解析获取域名 begin *************
    //解析IPV4记录
    let finalIps = await this.resolverHost(Alipdns.getInstance().QTYPE_V4,host);
    // ************* HTTPDNS解析获取域名 end *************
    
  /**
   * HTTPDNS 域名解析(缓存优先 + 网络兜底)
   * @param qtype - DNS 查询类型(如 Alipdns.getInstance().QTYPE_V4 //解析IPV4记录)
   * @param host - 目标域名
   * @returns 解析成功的 IP 数组
   */
  async resolverHost(qtype: string, host: string): Promise<string[]> {
    // ************* HTTPDNS解析:缓存 → 网络兜底 *************
    let finalIps: string[] = [];

    // 1. 优先从缓存获取 IP(参数三为true 允许返回过期但可用的记录)
    try {
      const cacheResult = Alipdns.getInstance().getIpsByHostFromCache(qtype, host, true);
      // 校验缓存结果
      if (Array.isArray(cacheResult) && cacheResult.length > 0) {
        finalIps = cacheResult;
        console.log(`pdns: [缓存命中] 域名 ${host} 解析结果: ${finalIps.join(', ')}`);
      } else {
        console.log(`pdns: [缓存未命中/无效] 域名 ${host},将发起网络请求`);
      }
    } catch (e) {
      console.warn(`pdns: 缓存查询异常: ${e?.message || e}`);
    }

    // 2. 缓存无效时,发起网络请求
    if (finalIps.length === 0) {
      try {
        finalIps = await this.getIpsFromNetwork(qtype, host);
        if (finalIps.length > 0) {
          console.log(`pdns: [网络请求成功] 域名 ${host} 解析结果: ${finalIps.join(', ')}`);
        } else {
          console.warn(`pdns: [网络请求] 域名 ${host} 返回空结果`);
        }
      } catch (err) {
        console.error(`pdns: [网络请求失败] 域名 ${host}: ${err?.message || JSON.stringify(err)}`);
        // 保持 finalIps 为空数组,后续走系统DNS
      }
    }
    return finalIps;
  }

  // 无缓存时网络请求解析域名获取 IP
  getIpsFromNetwork(qtype: string, domain: string): Promise<string[]> {
    return new Promise((resolve) => {
      Alipdns.getInstance().getIpsByHostAsync(qtype, domain, (ips: string[]) => {
        if (Array.isArray(ips)) {
          resolve(ips);
        } else {
          resolve([]);
        }
      });
    });
  }

2,适用于需要支持ipv6的场景

    //********适用于仅支持ipv6的场景*******
    
    // ************* HTTPDNS解析获取域名 begin *************
    // 解析IPV4和IPV6记录
    let finalIps = await this.resolverHost(Alipdns.getInstance().QTYPE_Auto,host);
    // ************* HTTPDNS解析获取域名 end *************
    
  /**
   * HTTPDNS 域名解析(缓存优先 + 网络兜底)
   * @param qtype - DNS 查询类型(如 Alipdns.getInstance().QTYPE_Auto //解析IPV4和IPV6记录)
   * @param host - 目标域名
   * @returns 解析成功的 IP 数组
   */
  async resolverHost(qtype: string, host: string): Promise<string[]> {
    // ************* HTTPDNS解析:缓存 → 网络兜底 *************
    let finalIps: string[] = [];

    // 1. 优先从缓存获取 IP(参数三为true 允许返回过期但可用的记录)
    try {
      const cacheResult = Alipdns.getInstance().getIpsByHostFromCache(qtype, host, true);
      // 校验缓存结果
      if (Array.isArray(cacheResult) && cacheResult.length > 0) {
        finalIps = cacheResult;
        console.log(`pdns: [缓存命中] 域名 ${host} 解析结果: ${finalIps.join(', ')}`);
      } else {
        console.log(`pdns: [缓存未命中/无效] 域名 ${host},将发起网络请求`);
      }
    } catch (e) {
      console.warn(`pdns: 缓存查询异常: ${e?.message || e}`);
    }

    // 2. 缓存无效时,发起网络请求
    if (finalIps.length === 0) {
      try {
        finalIps = await this.getIpsFromNetwork(qtype, host);
        if (finalIps.length > 0) {
          console.log(`pdns: [网络请求成功] 域名 ${host} 解析结果: ${finalIps.join(', ')}`);
        } else {
          console.warn(`pdns: [网络请求] 域名 ${host} 返回空结果`);
        }
      } catch (err) {
        console.error(`pdns: [网络请求失败] 域名 ${host}: ${err?.message || JSON.stringify(err)}`);
        // 保持 finalIps 为空数组,后续走系统DNS
      }
    }
    return finalIps;
  }

  // 无缓存时网络请求解析域名获取 IP
  getIpsFromNetwork(qtype: string, domain: string): Promise<string[]> {
    return new Promise((resolve) => {
      Alipdns.getInstance().getIpsByHostAsync(qtype, domain, (ips: string[]) => {
        if (Array.isArray(ips)) {
          resolve(ips);
        } else {
          resolve([]);
        }
      });
    });
  }

自建DNS

从 v2.0.0 版本起,HTTPDNS Harmony SDK 新增对 私有化部署的自建DNS 的支持。

自建DNS模式适用于对数据合规性、解析策略定制有更高要求的场景,例如金融、政务、大型互联网企业等。SDK 支持 纯公有云DNS、纯自建DNS、主备混合(公有云DNS+自建DNS互为兜底) 四种典型部署模式,灵活适配不同业务架构。

核心能力

  • 私有化部署支持:支持通过 IPv4/IPv6 地址或 Host 域名方式配置自建DNS 服务端点。

  • 双向鉴权机制:使用客户专属的 accessKeyId 和 accessKeySecret 进行请求签名,保障通信安全。

  • 熔断与健康检查:当某自建DNS 节点连续失败 ≥3 次时自动熔断,后续每分钟使用指定 healthCheckDomain 探测其可用性,恢复后自动重新启用。

  • 智能降级兜底:当主用 DNS(公有云DNS或自建DNS)解析失败达到阈值时,自动切换至备用 DNS,保障解析高可用。

  • 无缝兼容现有 API:无论使用公有云DNS还是自建DNS,上层调用解析接口的方式完全一致,无需修改业务逻辑。

配置说明

1. 仅使用公有云DNS

适用于未部署自建DNS 的标准 SaaS 用户。

let alipdns = Alipdns.getInstance();
alipdns.Init(this.context,AccountID,AccessKeID,AccessKeySecret);

2. 仅使用自建DNS(私有化部署)

适用于完全依赖自建DNS 的客户。

let alipdns = Alipdns.getInstance();
alipdns.InitFusionDNS(this.context,['1.1.X.X','2.2.X.X'],null, null,'443','熔断后健康检查域名','客户私有 accessKeyId','客户私有 accessKeySecret');

3. 公有云DNS为主,自建DNS为备

主用阿里云公共 HTTPDNS解析失败后,自动降级到自建DNS。

let alipdns = Alipdns.getInstance();

// 主用:公有云DNS
alipdns.Init(this.context,AccountID,AccessKeID,AccessKeySecret);
    
// 备用:自建DNS
alipdns.InitFusionDNS(this.context,['1.1.X.X','2.2.X.X'],null, null,'443','熔断后健康检查域名','客户私有 accessKeyId','客户私有 accessKeySecret');

4. 自建DNS为主,公有云DNS为备

主用自建DNS 解析失败后,自动降级到阿里云公有云DNS。

let alipdns = Alipdns.getInstance();
    
// 主用:自建DNS
alipdns.InitFusionDNS(this.context,['1.1.X.X','2.2.X.X'],null, null,'443','熔断后健康检查域名','客户私有 accessKeyId','客户私有 accessKeySecret');

// 备用:公有云DNS
alipdns.Init(this.context,AccountID,AccessKeID,AccessKeySecret);

新增服务 API

为支持自建DNS 的私有化部署与高可用容灾,SDK 新增以下三个核心接口,用于配置自建DNS服务、控制安全策略及实现主备自动降级。

1. 配置自建DNS 服务端点与鉴权信息

/**使用私有化部署的自建DNS相关,若只使用公共DNS不需要设置该方法
     *
     * 设置自建DNS 服务器地址和鉴权信息
     * 客户通过此接口传入私有 DNS 服务器的地址和鉴权凭证
     * SDK 将使用这些信息发起请求
     * @param ctx 上下文
     * @param serverIpv4Arr IPv4 地址数组(可为 nil)
     * @param serverIpv6Arr IPv6 地址数组(可为 nil)
     * @param serverHostArr Host 域名数组(可为 nil)
     * @param port 服务端口(如 "443",传 nil 使用默认"443")
     * @param healthCheckDomain 熔断后健康检查域名,当某个解析服务连续失败次数大于3次后,会触发熔断,该解析服务ip会进入healthCheck状态 (后续请求不会走该服务),
     *                          定时器每分钟会使用该healthCheckDomain调用解析接口探测该解析服务是否可以使用,如果探测成功,则恢复alive状态(后续请求可以走该服务)
     * @param accessKeyId 客户私有 accessKeyId(用于鉴权)
     * @param accessKeySecret 客户私有 accessKeySecret(用于鉴权)
     */
InitFusionDNS(
    ctx:Context,
    ipv4: string[] | null,
    ipv6: string[] | null,
    host: string[] | null,
    port: string | null,
    healthCheckDomain: string,
    accessKeyId: string,
    accessKeySecret: string
  )

2. 设置主备 DNS 自动降级阈值

/**公共云DNS和融合云DNS同时配置时,设置主用DNS解析失败多少次后自动降级到备用DNS来兜底,如果只配置一种DNS,不需要设置该方法
   *
   * 设置主用DNS解析失败多少次后自动降级到备用DNS来兜底,如果只配置一种DNS,不需要设置该方法
   * @param fallbackThreshold 次数(主用公共DNS时默认 4,主用融合DNS时默认2)
   *  范围[0-4]  设置0表示立即降级,最大4
   */
   
setFallbackThreshold(fallbackThreshold:number);