NodeJS 中 DNS 查询的坑 & DNS cache 分析
近期在做一个 DNS 服务器切换升级的演练中发现,我们在 NodeJS 中使用的 axios 以及默认的 dns.lookup 存在一些问题,会导致切换过程中的响应耗时从 ~80ms 上升至 ~3min,最终 nginx 层出现大量 502。 具体背景与分析参见 《node中请求超时的一些坑》 ➡️ 总结来说,NodeJS DNS 这块的“坑”可能有↓↓ 使用 http 模块发起请求(axios 也用的它),默认会使用 dns.lookup 来进行 DNS 查询,其底层调用了系统函数 getaddrinfo 。 getaddrinfo 会同步阻塞 ,所以使用线程池来模拟异步,默认数量为 4。因此如果 DNS 查询时间过长且并发请求多,则会导致整体事件循环(Event Loop)出现延迟(阻塞)。 如果 使用 axios 来设置 timeout ,在 0.19.0 之后 实际会调用 Request#setTimeout 方法,该方法的超时时间不包括 DNS 查询。因此如果你将超时设为 3s,但是 DNS 查询由于 DNS 服务器未响应挂起了 5s(甚至更久),这种情况下你的请求是不会被超时释放的。随着请求的越来越多问题会被累积,造成雪崩。 getaddrinfo 使用 resolv.conf 中 nameserver 配置作为本地 DNS 服务器,可以配置多个作为主从