DNS
使用 Bun 的 DNS 模組解析 DNS 記錄
Bun 實現了自己的 dns 模組和 node:dns 模組。
import * as dns from "node:dns";
const addrs = await dns.promises.resolve4("bun.com", { ttl: true });
console.log(addrs);
// => [{ address: "172.67.161.226", ttl: 0 }, ...]
import { dns } from "bun";
dns.prefetch("bun.com", 443);
選擇解析器後端
Bun.dns.lookup() 接受一個 backend 選項,用於選擇解析器實現:
"c-ares":非同步解析器 c-ares。它會直接讀取/etc/resolv.conf,因此不會查詢systemd-resolved等 NSS 模組。此後端是 Linux 上Bun.dns.lookup()的預設後端。"system":平臺自帶的解析器(macOS 上的非阻塞系統 API,以及其他平臺上的執行緒池getaddrinfo)。此後端是 macOS、Windows 和 Android 上的預設後端。"getaddrinfo"(別名"libc"):線上程池中呼叫 POSIXgetaddrinfo(3)函式。
import { dns } from "bun";
const [{ address }] = await dns.lookup("example.com", { backend: "system" });
node:dns.lookup() 始終使用 "system" 後端,以匹配 Node.js,因為 Node.js 的文件說明其 dns.lookup() 會呼叫 getaddrinfo(3)。node:dns.resolve*() 函式使用 c-ares,與 Node.js 中的行為一致。
Bun 中的 DNS 快取
Bun 會快取 DNS 查詢結果,從而加快與同一主機的重複連線。
快取最多儲存 256 個條目,每個條目的最長有效期為 30 秒。如果與某個主機的連線失敗,Bun 會從快取中移除該主機的條目。與同一主機的並行連線會共享一次 DNS 查詢。
Bun 會在以下場景中自動使用此快取:
bun installfetch()node:http(客戶端)Bun.connectnode:netnode:tls
什麼時候應該預獲取 DNS 記錄?
Web 瀏覽器提供了 <link rel="dns-prefetch">,可以在需要之前解析主機名。在 Bun 中,dns.prefetch 的作用相同:當你知道很快就會連線到某個主機,並希望避免首次 DNS 查詢時,可以使用它。
import { dns } from "bun";
dns.prefetch("my.database-host.com", 5432);
資料庫驅動是一個很好的例子:在應用程式啟動時預獲取資料庫主機的 DNS 條目。等應用程式的其餘部分載入完成時,查詢可能已經完成。
dns.prefetch
dns.prefetch 會在需要之前解析主機名。
dns.prefetch(hostname: string, port?: number): void;
範例:
import { dns } from "bun";
dns.prefetch("bun.com", 443);
//
// ... 過一段時間 ...
await fetch("https://bun.sh");
dns.getCacheStats()
dns.getCacheStats() 將當前快取統計資訊作為物件傳回,該物件包含以下屬性:
{
cacheHitsCompleted: number; // 已完成的快取命中次數
cacheHitsInflight: number; // 進行中的快取命中次數
cacheMisses: number; // 快取未命中次數
size: number; // DNS 快取條目數
errors: number; // 連線失敗次數
totalCount: number; // 總連線請求次數(包含快取命中和未命中)
}
範例:
import { dns } from "bun";
const stats = dns.getCacheStats();
console.log(stats);
// => { cacheHitsCompleted: 0, cacheHitsInflight: 0, cacheMisses: 0, size: 0, errors: 0, totalCount: 0 }
設定 DNS 快取 TTL
Bun 預設會將 DNS 條目快取 30 秒。若要更改 TTL,請設定 $BUN_CONFIG_DNS_TIME_TO_LIVE_SECONDS 環境變數。例如,以下命令會將其設定為 5 秒:
BUN_CONFIG_DNS_TIME_TO_LIVE_SECONDS=5 bun run my-script.ts
為什麼預設是 30 秒?
底層的系統 API(getaddrinfo)不會公開 DNS 條目的 TTL,因此 Bun 必須自行選擇一個數值。我們選擇 30 秒,是因為這個時長足以體現快取的優勢,同時又足夠短,在 DNS 條目發生變化時不太可能造成問題。Amazon Web Services 建議 Java 虛擬機器使用 5 秒,不過 JVM 的預設設定是無限期快取。