本文介绍如何在Node.js应用开发中集成使用HTTPDNS。
Node.js是一个基于Chrome V8引擎的JavaScript运行时环境,广泛应用于服务端开发、API构建、微服务架构等场景。
我们提供Node.js环境下的HTTPDNS SDK:httpdns-nodejs-sdk。Node.js应用可以集成SDK,并参考Node.js最佳实践来使用HTTPDNS能力。
以下是SDK的使用说明和最佳实践:
一、快速入门
1.1 开通服务
请参考快速入门开通HTTPDNS。
1.2 获取配置
请参考开发配置在EMAS控制台开发配置中获取AccountId/SecretKey等信息,用于初始化SDK。
二、安装
Node.js SDK及接入示例下载:httpdns-nodejs-sdk.zip。
三、配置和使用
3.1 初始化配置
应用启动后,需要先初始化SDK,才能调用HTTPDNS能力。初始化主要是配置AccountId/SecretKey等信息及功能开关。示例代码如下:
import { createClient } from 'httpdns-nodejs-sdk';
const client = createClient({
accountId: 'your-account-id',
secretKey: 'your-secret-key',
});
3.1.1 日志配置
应用开发过程中,如果要输出HTTPDNS的日志,可以在初始化时配置logger,示例代码如下:
const client = createClient({
...,
logger: console
});
3.2 域名解析
3.2.1 同步非阻塞解析(推荐)
推荐使用同步非阻塞解析方法,该方法立即返回缓存结果,不阻塞程序执行,示例代码如下:
function resolve() {
const result = client.getHttpDnsResultForHostSyncNonBlocking('www.aliyun.com');
if (result) {
console.log('解析结果:', result.ipv4);
console.log('域名:', result.domain);
console.log('IPv6:', result.ipv6);
console.log('TTL:', result.ttl);
console.log('成功:', result.success);
} else {
console.log('缓存未命中,异步解析中...');
// 异步解析已在后台启动,下次调用将返回结果
}
}
3.2.2 同步解析
当需要确保获取解析结果时,可以使用同步解析方法,该方法会等待解析完成,示例代码如下:
async function resolve() {
try {
const result = await client.getHttpDnsResultForHostSync('www.aliyun.com');
console.log('域名:', result.domain);
console.log('IPv4:', result.ipv4);
console.log('IPv6:', result.ipv6);
console.log('TTL:', result.ttl);
console.log('成功:', result.success);
} catch (error) {
console.error('解析失败:', error);
}
}
四、Node.js最佳实践
4.1 原理说明
在应用中创建自定义DNS lookup函数
需要使用HTTPDNS解析的请求,配置使用自定义lookup
在lookup函数中获取请求域名,通过HTTPDNS解析为IP
在lookup函数中返回解析后的IP,用于发起真正的请求,从而避免走LocalDNS进行解析
4.2 网络库集成
4.2.1 Axios集成
Axios集成通过Agent方式实现,核心步骤如下:
步骤1:创建自定义lookup函数
function createHTTPDNSLookup(httpdnsClient) {
return (hostname, options, callback) => {
// 标准化参数
if (typeof options === 'function') {
callback = options;
options = {};
}
// 确保callback存在
if (typeof callback !== 'function') {
throw new Error('callback must be a function');
}
// 使用 HTTPDNS 解析域名
const result = this.httpdnsClient.getHttpDnsResultForHostSyncNonBlocking(hostname);
if (result && result.success) {
const hasIPv4 = result.ipv4 && result.ipv4.length > 0;
const hasIPv6 = result.ipv6 && result.ipv6.length > 0;
if (hasIPv4 || hasIPv6) {
if (options && options.all) {
// 返回所有IP
const addresses = [
...(hasIPv4 ? result.ipv4.map(ip => ({ address: ip, family: 4 })) : []),
...(hasIPv6 ? result.ipv6.map(ip => ({ address: ip, family: 6 })) : [])
];
console.log(`[DNS Lookup] HTTPDNS 解析成功: ${hostname} -> 返回所有IP (${addresses.length}个)`);
callback(null, addresses);
} else {
// 优先IPv4,其次IPv6
if (hasIPv4) {
console.log(`[DNS Lookup] HTTPDNS 解析成功: ${hostname} -> ${result.ipv4[0]} (IPv4)`);
callback(null, result.ipv4[0], 4);
} else {
console.log(`[DNS Lookup] HTTPDNS 解析成功: ${hostname} -> ${result.ipv6[0]} (IPv6)`);
callback(null, result.ipv6[0], 6);
}
}
return;
}
}
console.log(`[DNS Lookup] HTTPDNS 无可用IP,降级到系统 DNS: ${hostname}`);
dns.lookup(hostname, options, callback);
};
}
步骤2:创建自定义Agent
const https = require('https');
const httpsAgent = new https.Agent({
lookup: createHTTPDNSLookup(httpdnsClient),
keepAlive: true,
maxSockets: 10
});
步骤3:创建Axios实例
const axios = require('axios');
const instance = axios.create({
httpsAgent: httpsAgent,
timeout: 10000
});
// 使用
const response = await instance.get('https://www.aliyun.com');
4.2.2 urllib集成
urllib集成同样使用Agent方式,核心步骤如下:
步骤1:创建自定义lookup函数
function createHTTPDNSLookup(httpdnsClient) {
return (hostname, options, callback) => {
// 标准化参数
if (typeof options === 'function') {
callback = options;
options = {};
}
// 确保callback存在
if (typeof callback !== 'function') {
throw new Error('callback must be a function');
}
// 使用 HTTPDNS 解析域名
const result = this.httpdnsClient.getHttpDnsResultForHostSyncNonBlocking(hostname);
if (result && result.success) {
const hasIPv4 = result.ipv4 && result.ipv4.length > 0;
const hasIPv6 = result.ipv6 && result.ipv6.length > 0;
if (hasIPv4 || hasIPv6) {
if (options && options.all) {
// 返回所有IP
const addresses = [
...(hasIPv4 ? result.ipv4.map(ip => ({ address: ip, family: 4 })) : []),
...(hasIPv6 ? result.ipv6.map(ip => ({ address: ip, family: 6 })) : [])
];
console.log(`[DNS Lookup] HTTPDNS 解析成功: ${hostname} -> 返回所有IP (${addresses.length}个)`);
callback(null, addresses);
} else {
// 优先IPv4,其次IPv6
if (hasIPv4) {
console.log(`[DNS Lookup] HTTPDNS 解析成功: ${hostname} -> ${result.ipv4[0]} (IPv4)`);
callback(null, result.ipv4[0], 4);
} else {
console.log(`[DNS Lookup] HTTPDNS 解析成功: ${hostname} -> ${result.ipv6[0]} (IPv6)`);
callback(null, result.ipv6[0], 6);
}
}
return;
}
}
console.log(`[DNS Lookup] HTTPDNS 无可用IP,降级到系统 DNS: ${hostname}`);
dns.lookup(hostname, options, callback);
};
}
步骤2:创建自定义Agent
const urllib = require('urllib');
const https = require('https');
const httpsAgent = new https.Agent({
lookup: createHTTPDNSLookup(httpdnsClient),
keepAlive: true,
maxSockets: 10
});
步骤3:发起请求
async function request(url, options = {}) {
// 根据URL类型选择Agent
if (url.startsWith('https://')) {
options.httpsAgent = httpsAgent;
} else {
options.agent = httpAgent; // 类似创建httpAgent
}
options.timeout = options.timeout || 10000;
try {
return await urllib.request(url, options);
} catch (error) {
// 自动重试逻辑
if (isConnectionError(error) && !options._retried) {
options._retried = true;
delete options.httpsAgent; // 使用系统DNS重试
return await urllib.request(url, options);
}
throw error;
}
}
五、API
5.1 初始化
初始化配置,在应用启动时调用。
const { createClient } = require('httpdns-nodejs-sdk');
const client = createClient({
accountId: 'your-account-id',
secretKey: 'your-secret-key'
});
参数:
参数名 | 类型 | 是否必须 | 功能 |
accountId | String | 必选参数 | Account ID |
secretKey | String | 可选参数 | 加签密钥 |
bootstrapIPs | Array | 可选参数 | 启动IP列表 |
timeout | Number | 可选参数 | 解析超时时间 |
maxRetries | Number | 可选参数 | 最大重试次数 |
enableHTTPS | Boolean | 可选参数 | 是否使用HTTPS |
enableCache | Boolean | 可选参数 | 是否缓存IP |
logger | Object | 可选参数 | 日志记录器 |
5.2 同步解析
解析指定域名。
const result = await client.getHttpDnsResultForHostSync('www.aliyun.com');
console.log('解析结果:', result);
参数:
参数名 | 类型 | 是否必须 | 功能 |
domain | String | 必选参数 | 域名 |
options | Object | 可选参数 | 解析选项 |
返回JSON字段说明:
字段名 | 类型 | 功能 |
domain | String | 域名 |
ipv4 | Array | v4类型的ip列表 |
ipv6 | Array | v6类型的ip列表 |
ttl | Number | 过期时间 |
success | Boolean | 解析是否成功 |
timestamp | Date | 解析时间戳 |
5.3 同步非阻塞解析
立即返回缓存结果,不阻塞等待。
const result = client.getHttpDnsResultForHostSyncNonBlocking('www.aliyun.com');
if (result) {
console.log('缓存结果:', result.ipv4);
}
5.4 客户端管理
获取客户端状态和管理客户端生命周期。
// 检查客户端健康状态
const isHealthy = client.isHealthy();
// 获取当前服务IP列表
const serviceIPs = client.getServiceIPs();
// 手动更新服务IP
await client.updateServiceIPs();
// 关闭客户端
await client.close();
六、总结
本文介绍了Node.js环境下HTTPDNS SDK的使用方法和最佳实践。通过Agent方式集成网络库,可以实现高性能、高可用的域名解析服务。主要特点包括:
简单易用:提供简洁的API接口,支持同步和同步非阻塞解析
高可用性:支持故障转移和降级策略,确保服务稳定性
性能优化:内置缓存机制和连接复用,提升解析效率
安全可靠:支持鉴权解析和HTTPS通信,保障数据安全
通过遵循本文的最佳实践建议,开发者可以在Node.js应用中高效地集成HTTPDNS服务。