Bun

DNS

Bun 實作了 node:dns 模組。

import * as dns from "node:dns";

const addrs = await dns.promises.resolve4("bun.sh", { ttl: true });
console.log(addrs);
// => [{ address: "172.67.161.226", family: 4, ttl: 0 }, ...]

Bun 中的 DNS 快取

在 Bun v1.1.9 版本中,我們加入了 DNS 快取的支援。這個快取機制讓重複連線到相同主機的速度更快。

在撰寫本文時,我們最多快取 255 個項目,每個項目的最長快取時間為 30 秒。如果連線到主機失敗,我們會從快取中移除該項目。當同時對同一主機建立多個連線時,DNS 查詢會被去重複化,以避免對同一主機發出多個請求。

此快取會自動被以下項目使用:

  • bun install
  • fetch()
  • node:http (client)
  • Bun.connect
  • node:net
  • node:tls

我應該在何時預先提取 DNS 項目?

網頁瀏覽器公開了 <link rel="dns-prefetch"> 以允許開發人員預先提取 DNS 項目。當您知道在不久的將來需要連線到某個主機,並希望避免初始 DNS 查詢時,這非常有用。

在 Bun 中,您可以使用 dns.prefetch API 來達到相同的效果。

import {dns} from "bun";

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

一個您可能想要使用此功能的範例是資料庫驅動程式。當您的應用程式首次啟動時,您可以預先提取資料庫主機的 DNS 項目,以便在應用程式完成所有載入時,解析資料庫主機的 DNS 查詢可能已經完成。

dns.prefetch

🚧 — 此 API 為實驗性功能,未來可能會變更。

若要預先提取 DNS 項目,您可以使用 dns.prefetch API。當您知道很快需要連線到某個主機,並希望避免初始 DNS 查詢時,此 API 非常有用。

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

範例:

import {dns} from "bun";

dns.prefetch("bun.sh", 443);
//
// ... sometime later ...
await fetch("https://bun.dev.org.tw");

dns.getCacheStats()

🚧 — 此 API 為實驗性功能,未來可能會變更。

若要取得目前的快取統計資訊,您可以使用 dns.getCacheStats API。

此 API 會傳回一個具有以下屬性的物件:

{
  // Cache hits 
  cacheHitsCompleted: number;
  cacheHitsInflight: number;
  cacheMisses: number;
  // Number of items in the DNS cache
  size: number;

  // Number of times a connection failed
  errors: number;

  // Number of times a connection was requested at all (including cache hits and misses)
  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 快取項目的 TTL 設定為 30 秒。若要變更此設定,您可以設定環境變數 $BUN_CONFIG_DNS_TIME_TO_LIVE_SECONDS。例如,若要將 TTL 設定為 5 秒:

BUN_CONFIG_DNS_TIME_TO_LIVE_SECONDS=5 bun run my-script.ts

為什麼預設值是 30 秒?

遺憾的是,底層的系統 API (getaddrinfo) 並未提供取得 DNS 項目 TTL 的方法。這表示我們必須任意選擇一個數字。我們選擇 30 秒是因為它夠長,可以展現快取的優點,又夠短,在 DNS 項目變更時不太可能造成問題。Amazon Web Services 建議 Java 虛擬機使用 5 秒,但 JVM 預設為無限期快取。