執行環境套件管理器打包器測試執行器程式碼檢查格式化指南參考部落格意見回饋

DNS

使用 Bun 的 DNS 模組解析 DNS 記錄

Bun 實現了自己的 dns 模組和 node:dns 模組。

TypeScript
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 }, ...]
TypeScript
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"):線上程池中呼叫 POSIX getaddrinfo(3) 函式。
TypeScript
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 install
  • fetch()
  • node:http(客戶端)
  • Bun.connect
  • node:net
  • node:tls

什麼時候應該預獲取 DNS 記錄?

Web 瀏覽器提供了 <link rel="dns-prefetch">,可以在需要之前解析主機名。在 Bun 中,dns.prefetch 的作用相同:當你知道很快就會連線到某個主機,並希望避免首次 DNS 查詢時,可以使用它。

TypeScript
import { dns } from "bun";

dns.prefetch("my.database-host.com", 5432);

資料庫驅動是一個很好的例子:在應用程式啟動時預獲取資料庫主機的 DNS 條目。等應用程式的其餘部分載入完成時,查詢可能已經完成。

dns.prefetch

dns.prefetch 會在需要之前解析主機名。

TypeScript
dns.prefetch(hostname: string, port?: number): void;

範例:

TypeScript
import { dns } from "bun";

dns.prefetch("bun.com", 443);
//
// ... 過一段時間 ...
await fetch("https://bun.sh");

dns.getCacheStats()

dns.getCacheStats() 將當前快取統計資訊作為物件傳回,該物件包含以下屬性:

TypeScript
{
  cacheHitsCompleted: number; // 已完成的快取命中次數
  cacheHitsInflight: number;  // 進行中的快取命中次數
  cacheMisses: number;        // 快取未命中次數
  size: number;               // DNS 快取條目數
  errors: number;             // 連線失敗次數
  totalCount: number;         // 總連線請求次數(包含快取命中和未命中)
}

範例:

TypeScript
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 秒:

shell
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 的預設設定是無限期快取。