本文介紹如何在Node.js應用開發中整合使用HTTPDNS。
Node.js是一個基於Chrome V8引擎的JavaScript運行時環境,廣泛應用於服務端開發、API構建、微服務架構等情境。
我們提供Node.js環境下的HTTPDNS SDK:@alicloud-emas/httpdns。Node.js應用可以整合SDK,並參考Node.js最佳實務來使用HTTPDNS能力。
以下是SDK的使用說明和最佳實務:
一、快速入門
1.1 開通服務
請參考快速入門開通HTTPDNS。
1.2 擷取配置
請參考開發配置在EMAS控制台開發配置中擷取AccountId/SecretKey等資訊,用於初始化SDK。
二、安裝
通過npm安裝:
npm install @alicloud-emas/httpdns接入樣本:
參考 GitHub 倉庫中的範例程式碼和文檔。
三、配置和使用
3.1 初始化配置
應用啟動後,需要先初始化SDK,才能調用HTTPDNS能力。初始化主要是配置AccountId/SecretKey等資訊及功能開關。範例程式碼如下:
import { createClient } from '@alicloud-emas/httpdns';
const client = createClient({
accountId: 'your-account-id',
secretKey: 'your-secret-key',
enableExpiredIP: true,
enableHTTPS: true,
});
enableHTTPS參數設定為true後,計費會增加,請仔細閱讀產品計費文檔。
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);
} 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);
} 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函數
const dns = require('dns');
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 = httpdnsClient.getHttpDnsResultForHostSyncNonBlocking(hostname);
if (result) {
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函數
const dns = require('dns');
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 = httpdnsClient.getHttpDnsResultForHostSyncNonBlocking(hostname);
if (result) {
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('@alicloud-emas/httpdns');
const client = createClient({
accountId: 'your-account-id',
secretKey: 'your-secret-key',
timeout: 5000, // 解析逾時時間(毫秒)
maxRetries: 1, // 最大重試次數
enableHTTPS: false, // 是否使用HTTPS
enableCache: true, // 是否緩衝IP
enableExpiredIP: true, // 是否允許使用到期IP
});
參數:
參數名 | 類型 | 是否必須 | 功能 |
accountId | String | 必選參數 | Account ID |
secretKey | String | 選擇性參數 | 加簽密鑰 |
bootstrapIPs | Array | 選擇性參數 | 啟動IP列表 |
timeout | Number | 選擇性參數 | 解析逾時時間 |
maxRetries | Number | 選擇性參數 | 最大重試次數 |
enableHTTPS | Boolean | 選擇性參數 | 是否使用HTTPS |
enableCache | Boolean | 選擇性參數 | 是否緩衝IP |
logger | Object | 選擇性參數 | 日誌記錄器 |
enableExpiredIP | Boolean | 選擇性參數 | 是否允許使用到期IP |
enableHTTPS參數設定為true後,計費會增加,請仔細閱讀產品計費文檔。
5.2 預解析網域名稱
設定預解析網域名稱列表,以便SDK提前解析,減少後續網域名稱解析時請求的時延。
// 設定預解析列表
client.setPreResolveHosts(['www.aliyun.com']);
5.3 同步非阻塞解析
解析指定網域名稱,立即返回緩衝結果,不阻塞等待。
const result = client.getHttpDnsResultForHostSyncNonBlocking('www.aliyun.com');
if (result) {
console.log('緩衝結果:', result.ipv4);
}
參數:
參數名 | 類型 | 是否必須 | 功能 |
domain | String | 必選參數 | 網域名稱 |
options | Object | 選擇性參數 | 解析選項 |
返回JSON欄位說明:
欄位名 | 類型 | 功能 |
domain | String | 網域名稱 |
ipv4 | Array | v4類型的ip列表 |
ipv6 | Array | v6類型的ip列表 |
ipv4Ttl | Number | v4到期時間 |
ipv6Ttl | Number | v6到期時間 |
ipv4Timestamp | Date | v4解析時間戳記 |
ipv6Timestamp | Date | v6解析時間戳記 |
5.4 同步解析
同步解析指定網域名稱。
const result = await client.getHttpDnsResultForHostSync('www.aliyun.com');
console.log('解析結果:', result);
5.5 用戶端管理
擷取用戶端狀態和管理用戶端生命週期。
// 檢查用戶端健康狀態
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服務。