穩(wěn)定性: 3 - 穩(wěn)定
本節(jié)將介紹Node.js的DNS模塊,你可以通過調(diào)用require('dns')
來訪問DNS模塊。
DNS模塊包含的函數(shù)屬于2個不同的分類:
1)使用系統(tǒng)底層的特性,完成名字解析,這個過程不需要網(wǎng)絡(luò)通訊,這個分類僅有一個函數(shù):dns.lookup
。開發(fā)者在同一個系統(tǒng)里名字解析都是用 dns.lookup
。
下面的例子解析了www.google.com
:
var dns = require('dns');
dns.lookup('www.google.com', function onLookup(err, addresses, family) {
console.log('addresses:', addresses);
});
2)連接到DNS服務(wù)器進(jìn)行名字解析,始終使用網(wǎng)絡(luò)來進(jìn)行域名查詢。這個分類包含除了dns.lookup
外的所有函數(shù)。這些函數(shù)不會和dns.lookup
使用同一套配置文件。如果你不想使用系統(tǒng)底層的特性來進(jìn)行名字解析,而想進(jìn)行DNS查詢的話,可以使用這個分類的函數(shù)。
下面的例子,解析了'www.google.com'
,并反向解析返回的IP地址:
var dns = require('dns');
dns.resolve4('www.google.com', function (err, addresses) {
if (err) throw err;
console.log('addresses: ' + JSON.stringify(addresses));
addresses.forEach(function (a) {
dns.reverse(a, function (err, hostnames) {
if (err) {
throw err;
}
console.log('reverse for ' + a + ': ' + JSON.stringify(hostnames));
});
});
});
更多細(xì)節(jié)參考Implementation considerations section。
將域名(比如'google.com'
)解析為第一條找到的記錄A (IPV4)或AAAA(IPV6)。參數(shù)options
可以是一個對象或整數(shù)。如果沒有提供options
,IP v4和 v6地址都可以。如果options
是整數(shù),則必須是4
或6
。
options
參數(shù)可能是包含family
和hints
兩個屬性的對象。這兩個屬性都是可選的。如果提供了family
,則必須是4
或6
,否則,IP v4和v6地址都可以。如果提供了hints
,可以是一個或者多個getaddrinfo
標(biāo)志,若不提供,沒有標(biāo)志會傳給getaddrinfo
。多個標(biāo)志位可以通過或運算來整合。以下的例子展示如何使用options
。
{
family: 4,
hints: dns.ADDRCONFIG | dns.V4MAPPED
}
參見supported getaddrinfo
flags 查看更多的標(biāo)志位。
回調(diào)函數(shù)包含參數(shù) (err, address, family)
。address
參數(shù)表示IP v4或v6地址。family
參數(shù)是4或6,表示address
家族(不一定是之前傳入lookup的值)。
出錯時,參數(shù)err
是Error
對象,err.code
是錯誤代碼。請記住,err.code
等于'ENOENT'
,不僅可能是因為域名不存在,還有可能是是其他原因,比如沒有可用文件描述符。
dns.lookup
不必和DNS協(xié)議有關(guān)系。它使用了操作系統(tǒng)的特性,能將名字和地址關(guān)聯(lián)。
實現(xiàn)這些東西也許很簡單,但是對于 Node.js 程序來說都重要,所以在使用前請花點時間閱讀Implementation considerations section。
使用getnameinfo
解析傳入的地址和端口為域名和服務(wù)。
這個回調(diào)函數(shù)的參數(shù)是(err, hostname, service)
。hostname
和service
都是字符串 (比如'localhost'
和'http'
)。
出錯時,參數(shù)err
是Error
對象,err.code
是錯誤代碼。
將一個域名(如'google.com')解析為一個rrtype指定記錄類型的數(shù)組。
有效的rrtypes值為:
'A'
(IPV4地址,默認(rèn))'AAAA'
(IPV6地址)'MX'
(郵件交換記錄)'TXT'
(text記錄)'SRV'
(SRV記錄)'PTR'
(用來反向IP查找)'NS'
(域名服務(wù)器記錄)'CNAME'
(別名記錄)'SOA'
(授權(quán)記錄的初始值)回調(diào)參數(shù)為(err, addresses)
. 其中addresses
中每一項的類型都取決于記錄類型,詳見下文對應(yīng)的查找方法。
出錯時,參數(shù)err
是 Error
對象,err.code
是錯誤代碼。
和dns.resolve()
類似,僅能查詢IPv4 (A
記錄)。addresses
IPv4地址數(shù)組 (比如,['74.125.79.104', '74.125.79.105', '74.125.79.106']
)。
和dns.resolve4()
類似,僅能查詢 IPv4(AAAA
查詢)。
和dns.resolve()
類似,僅能查詢郵件交換(MX
記錄)。
addresses
是MX記錄數(shù)組,每一個包含優(yōu)先級和交換屬性(比如,[{'priority': 10, 'exchange': 'mx.example.com'},...]
)。
和dns.resolve()
類似,僅能進(jìn)行文本查詢 (TXT
記錄)。addresses
是2-d文本記錄數(shù)組。(比如,[ ['v=spf1 ip4:0.0.0.0 ', '~all' ] ]
)。每個子數(shù)組包含一條記錄的TXT塊。根據(jù)使用情況可以連接在一起,也可單獨使用。
和dns.resolve()
類似,僅能進(jìn)行服務(wù)記錄查詢 (SRV
記錄)。addresses
是hostname
可用的SRV記錄數(shù)組。SRV記錄屬性有優(yōu)先級(priority),權(quán)重(weight), 端口(port), 和名字(name) (比如,[{'priority': 10, 'weight': 5, 'port': 21223, 'name': 'service.example.com'}, ...]
)。
和dns.resolve()
類似,僅能查詢權(quán)威記錄(SOA
記錄)。
addresses
是包含以下結(jié)構(gòu)的對象:
{
nsname: 'ns.example.com',
hostmaster: 'root.example.com',
serial: 2013101809,
refresh: 10000,
retry: 2400,
expire: 604800,
minttl: 3600
}
和dns.resolve()
類似,僅能進(jìn)行域名服務(wù)器記錄查詢(NS
記錄)。addresses
是域名服務(wù)器記錄數(shù)組(hostname
可以使用) (比如,['ns1.example.com', 'ns2.example.com']
)。
和dns.resolve()
類似,僅能進(jìn)行別名記錄查詢 (CNAME
記錄)。addresses
是對hostname
可用的別名記錄數(shù)組 (比如,['bar.example.com']
)。
反向解析IP地址,返回指向該IP地址的域名數(shù)組。
回調(diào)函數(shù)參數(shù)(err, hostnames)
。
出錯時,參數(shù)err
是Error
對象,err.code
是錯誤代碼。
返回一個用于當(dāng)前解析的IP地址的數(shù)組的字符串。
指定一組IP地址作為解析服務(wù)器。
如果你給地址指定了端口,端口會被忽略,因為底層庫不支持。
傳入無效參數(shù),會拋出以下錯誤:
每個DNS查詢都可能返回以下錯誤:
dns.NODATA
: DNS服務(wù)器返回?zé)o數(shù)據(jù)應(yīng)答。 dns.FORMERR
: DNS服務(wù)器聲稱查詢格式錯誤。 dns.SERVFAIL
: DNS服務(wù)器返回一般失敗。 dns.NOTFOUND
: 沒有找到域名。 dns.NOTIMP
: DNS服務(wù)器未實現(xiàn)請求的操作。 dns.REFUSED
: DNS服務(wù)器拒絕查詢。 dns.BADQUERY
: DNS查詢格式錯誤。 dns.BADNAME
: 域名格式錯誤。 dns.BADFAMILY
: 地址協(xié)議不支持。 dns.BADRESP
: DNS回復(fù)格式錯誤。 dns.CONNREFUSED
: 無法連接到DNS服務(wù)器。 dns.TIMEOUT
: 連接DNS服務(wù)器超時。 dns.EOF
: 文件末端。 dns.FILE
: 讀文件錯誤。 dns.NOMEM
: 內(nèi)存溢出。 dns.DESTRUCTION
: 通道被摧毀。 dns.BADSTR
: 字符串格式錯誤。 dns.BADFLAGS
: 非法標(biāo)識符。 dns.NONAME
: 所給主機(jī)不是數(shù)字。 dns.BADHINTS
: 非法HINTS標(biāo)識符。 dns.NOTINITIALIZED
: c c-ares庫尚未初始化。 dns.LOADIPHLPAPI
: 加載iphlpapi.dll出錯。 dns.ADDRGETNETWORKPARAMS
: 無法找到GetNetworkParams函數(shù)。 dns.CANCELLED
: 取消DNS查詢。 以下內(nèi)容可作為hints標(biāo)志傳給dns.lookup
dns.ADDRCONFIG
: 返回當(dāng)前系統(tǒng)支持的地址類型。例如,如果當(dāng)前系統(tǒng)至少配置了一個IPv4地址,則返回IPv4地址。dns.V4MAPPED
: 如果指定了IPv6家族, 但是沒有找到IPv6地址,將返回IPv4映射的IPv6地址。雖然dns.lookup
和dns.resolve*/dns.reverse
函數(shù)都能實現(xiàn)網(wǎng)絡(luò)名和網(wǎng)絡(luò)地址的關(guān)聯(lián),但是他們的行為不太一樣。這些不同點雖然很巧妙,但是會對Node.js程序產(chǎn)生顯著的影響。
dns.lookup
和絕大多數(shù)程序一樣使用了相同的系統(tǒng)特性。例如,dns.lookup
和ping
命令用相同的方法解析了一個指定的名字。多數(shù)類似POSIX的系統(tǒng),dns.lookup
函數(shù)可以通過改變nsswitch.conf(5)
和/或resolv.conf(5)
的設(shè)置調(diào)整。如果改變這些文件將會影響系統(tǒng)里的其他應(yīng)用。
雖然,JavaScript調(diào)用是異步的,它的實現(xiàn)是同步的調(diào)用libuv線程池里的getaddrinfo(3)
。因為libuv線程池固定大小,所以如果調(diào)用getaddrinfo(3)
的時間太長,會使的池里的其他操作(比如文件操作)性能降低。為了降低這個風(fēng)險,可以通過增加'UV_THREADPOOL_SIZE'的值,讓它超過4,來調(diào)整libuv線程池大小,更多信息參見[the official libuvdocumentation](http://docs.libuv.org/en/latest/threadpool.html)。
這些函數(shù)的實現(xiàn)和dns.lookup
不大相同。他們不會用到getaddrinfo(3)
,而是始終進(jìn)行網(wǎng)絡(luò)查詢。這些操作都是異步的,和libuv線程池?zé)o關(guān)。
因此,這些操作對于其他線程不會產(chǎn)生負(fù)面影響,這和dns.lookup
不同。
它們不會用到dns.lookup
的配置文件(例如 ,/etc/hosts
_)。
更多建議: