Skip to main content
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", family: 4, ttl: 0 }, ...]
import { dns } from "bun";

dns.prefetch("bun.com", 443);

Bun 中的 DNS 缓存

Bun 支持 DNS 缓存。该缓存可以加快对相同主机的重复连接速度。 撰写本文时,我们缓存最多 255 条记录,最大缓存时间为 30 秒(每条记录)。如果连接主机失败,会从缓存中移除该条目。当对同一主机同时发起多个连接时,会去重 DNS 查询,避免对同一主机发起多次请求。 以下操作会自动使用此缓存:
  • bun install
  • fetch()
  • node:http(客户端)
  • 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.com", 443);
//
// ... 过一段时间 ...
await fetch("https://bun.com");

dns.getCacheStats()

此 API 处于实验阶段,将来可能会发生变化。
要获取当前缓存状态,可以使用 dns.getCacheStats API。此 API 返回一个包含以下属性的对象:
{
  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 缓存条目 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 记录变更时引发问题。亚马逊云服务建议 Java 虚拟机设置为 5 秒,但 JVM 默认情况下缓存时间无限。